diff --git a/examples/htool_key_rotation.c b/examples/htool_key_rotation.c index f5cf655..61781ca 100644 --- a/examples/htool_key_rotation.c +++ b/examples/htool_key_rotation.c @@ -28,9 +28,80 @@ #include "htool.h" #include "htool_cmd.h" +#include "protocol/host_cmd.h" #include "protocol/key_rotation.h" -static const char *get_validation_method_string(uint32_t validation_method) { +static const char* get_error_code_string(enum key_rotation_err err) { + if (err < KEY_ROTATION_ERR_HOTH_BASE) { + switch (err) { + case KEY_ROTATION_CMD_SUCCESS: + return "Success"; + case KEY_ROTATION_INTERNAL_ERR: + return "Internal Error"; + case KEY_ROTATION_ERR_INVALID_PARAM: + return "Invalid Parameter"; + case KEY_ROTATION_ERR_INVALID_RESPONSE_SIZE: + return "Invalid Response Size"; + case KEY_ROTATION_INITIATE_FAIL: + return "Key Rotation Record Initiate Failed"; + case KEY_ROTATION_COMMIT_FAIL: + return "Key Rotation Record Commit Failed"; + case KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE: + return "Root of Trust Unavailable"; + default: + return "Unknown"; + } + } + int ret = err - KEY_ROTATION_ERR_HOTH_BASE; + switch (ret) { + case HOTH_RES_SUCCESS: + return "Success"; + case HOTH_RES_INVALID_COMMAND: + return "Key Rotation Feature Not Supported"; + case HOTH_RES_ERROR: + return "Hoth Error"; + case HOTH_RES_INVALID_PARAM: + return "Invalid Parameter"; + case HOTH_RES_ACCESS_DENIED: + return "Access Denied"; + case HOTH_RES_INVALID_RESPONSE: + return "Invalid Response"; + case HOTH_RES_INVALID_VERSION: + return "Invalid Version"; + case HOTH_RES_INVALID_CHECKSUM: + return "Invalid Checksum"; + case HOTH_RES_IN_PROGRESS: + return "In Progress"; + case HOTH_RES_UNAVAILABLE: + return "Unavailable"; + case HOTH_RES_TIMEOUT: + return "Timeout"; + case HOTH_RES_OVERFLOW: + return "Overflow"; + case HOTH_RES_INVALID_HEADER: + return "Invalid Header"; + case HOTH_RES_REQUEST_TRUNCATED: + return "Request Truncated"; + case HOTH_RES_RESPONSE_TOO_BIG: + return "Response Too Big"; + case HOTH_RES_BUS_ERROR: + return "Bus Error"; + case HOTH_RES_BUSY: + return "Busy"; + case HOTH_RES_INVALID_HEADER_VERSION: + return "Invalid Header Version"; + case HOTH_RES_INVALID_HEADER_CRC: + return "Invalid Header CRC"; + case HOTH_RES_INVALID_DATA_CRC: + return "Invalid Data CRC"; + case HOTH_RES_DUP_UNAVAILABLE: + return "Duplicate Request Unavailable"; + default: + return "Unknown"; + } +} + +static const char* get_validation_method_string(uint32_t validation_method) { switch (validation_method) { case 1: return "Embedded Key"; @@ -46,11 +117,14 @@ static const char *get_validation_method_string(uint32_t validation_method) { int htool_key_rotation_get_status(void) { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } struct hoth_response_key_rotation_status status; enum key_rotation_err ret = libhoth_key_rotation_get_status(dev, &status); if (ret) { + fprintf(stderr, "HOTH_KEY_ROTATION_GET_STATUS error: %s\n", + get_error_code_string(ret)); fprintf(stderr, "Failed to get key rotation status\n"); return -1; } @@ -68,11 +142,14 @@ int htool_key_rotation_get_status(void) { int htool_key_rotation_get_version(void) { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } struct hoth_response_key_rotation_record_version version; enum key_rotation_err ret = libhoth_key_rotation_get_version(dev, &version); if (ret) { + fprintf(stderr, "HOTH_KEY_ROTATION_GET_VERSION error: %s\n", + get_error_code_string(ret)); fprintf(stderr, "Failed to get key rotation version\n"); return -1; } @@ -132,6 +209,7 @@ static int read_image_file(const char *image_file, uint8_t **image, int htool_key_rotation_update(const struct htool_invocation *inv) { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } const char *image_file; @@ -148,6 +226,8 @@ int htool_key_rotation_update(const struct htool_invocation *inv) { enum key_rotation_err key_ret = libhoth_key_rotation_update(dev, image, size); if (key_ret) { + fprintf(stderr, "HOTH_KEY_ROTATION_UPDATE error: %s\n", + get_error_code_string(key_ret)); fprintf(stderr, "Failed to update key rotation record\n"); result = key_ret; } @@ -164,12 +244,15 @@ int htool_key_rotation_update(const struct htool_invocation *inv) { int htool_key_rotation_payload_status() { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } struct hoth_response_key_rotation_payload_status payload_status; enum key_rotation_err ret = libhoth_key_rotation_payload_status(dev, &payload_status); if (ret) { + fprintf(stderr, "HOTH_KEY_ROTATION_PAYLOAD_STATUS error: %s\n", + get_error_code_string(ret)); fprintf(stderr, "Failed to get key rotation payload status\n"); return -1; } @@ -201,6 +284,7 @@ static int get_key_rotation_read_half(const char *read_half, int htool_key_rotation_read(const struct htool_invocation *inv) { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } uint32_t offset = 0; @@ -246,6 +330,8 @@ int htool_key_rotation_read(const struct htool_invocation *inv) { enum key_rotation_err ret_read = libhoth_key_rotation_read(dev, offset, size, read_half, &read_response); if (ret_read) { + fprintf(stderr, "HOTH_KEY_ROTATION_READ error: %s\n", + get_error_code_string(ret_read)); fprintf(stderr, "Failed to read key rotation record\n"); if (fd != -1) { close(fd); @@ -296,6 +382,7 @@ static int get_key_rotation_chunk_type(const char *chunk_type_string, int htool_key_rotation_read_chunk_type(const struct htool_invocation *inv) { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } uint32_t offset = 0; @@ -345,6 +432,8 @@ int htool_key_rotation_read_chunk_type(const struct htool_invocation *inv) { dev, chunk_typecode, chunk_index, offset, size, &read_response, &response_size); if (ret_read) { + fprintf(stderr, "HOTH_KEY_ROTATION_READ_CHUNK_TYPE error: %s\n", + get_error_code_string(ret_read)); fprintf(stderr, "Failed to read chunk from key rotation record\n"); return -1; } @@ -385,6 +474,7 @@ int htool_key_rotation_read_chunk_type(const struct htool_invocation *inv) { int htool_key_rotation_chunk_type_count(const struct htool_invocation *inv) { struct libhoth_device *dev = htool_libhoth_device(); if (!dev) { + fprintf(stderr, "Failed to get libhoth device\n"); return -1; } const char *chunk_type_string; @@ -401,6 +491,8 @@ int htool_key_rotation_chunk_type_count(const struct htool_invocation *inv) { enum key_rotation_err ret_count = libhoth_key_rotation_chunk_type_count(dev, chunk_typecode, &chunk_count); if (ret_count) { + fprintf(stderr, "HOTH_KEY_ROTATION_CHUNK_TYPE_COUNT error: %s\n", + get_error_code_string(ret_count)); fprintf(stderr, "Failed to get chunk type count\n"); return -1; } diff --git a/examples/htool_secure_boot.c b/examples/htool_secure_boot.c index a0cbab2..a7d69d5 100644 --- a/examples/htool_secure_boot.c +++ b/examples/htool_secure_boot.c @@ -12,13 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +<<<<<<< HEAD #include "examples/htool_secure_boot.h" +======= +#include "htool_secure_boot.h" +>>>>>>> b127e59 (Improve key rotation error reporting in htool.) #include #include #include "examples/htool.h" +<<<<<<< HEAD #include "examples/htool_cmd.h" +======= +#include "htool_cmd.h" +>>>>>>> b127e59 (Improve key rotation error reporting in htool.) #include "protocol/secure_boot.h" int htool_secure_boot_get_enforcement(const struct htool_invocation* inv) { diff --git a/examples/htool_secure_boot.h b/examples/htool_secure_boot.h index 465ad56..97c9d09 100644 --- a/examples/htool_secure_boot.h +++ b/examples/htool_secure_boot.h @@ -15,7 +15,11 @@ #ifndef LIBHOTH_EXAMPLES_HTOOL_SECURE_BOOT_H_ #define LIBHOTH_EXAMPLES_HTOOL_SECURE_BOOT_H_ +<<<<<<< HEAD #include "examples/htool_cmd.h" +======= +#include "htool_cmd.h" +>>>>>>> b127e59 (Improve key rotation error reporting in htool.) #ifdef __cplusplus extern "C" { diff --git a/protocol/key_rotation.c b/protocol/key_rotation.c index 6c02e73..d024294 100644 --- a/protocol/key_rotation.c +++ b/protocol/key_rotation.c @@ -27,6 +27,39 @@ struct hoth_request_variable_length { uint8_t data[KEY_ROTATION_RECORD_WRITE_MAX_SIZE]; } __hoth_align4; +int get_command_version(struct libhoth_device* dev, uint16_t command, + uint8_t* version) { + fprintf(stderr, "HOTH_GET_CMD_VERSIONS\n"); + size_t rlen = 0; + int ret = libhoth_hostcmd_exec( + dev, HOTH_CMD_BOARD_SPECIFIC_BASE + HOTH_PRV_CMD_HAVEN_GET_CMD_VERSIONS, + 0, &command, sizeof(command), NULL, 0, &rlen); + if (ret != 0) { + return ret; + } + if (rlen != 0) { + fprintf(stderr, + "HOTH_GET_CMD_VERSIONS expected exactly %d response " + "bytes, got %ld\n", + 0, rlen); + return ret; + } + *version = rlen; + return 0; +} + +enum key_rotation_err get_key_rotation_error(int ret) { + fprintf(stderr, "HTOOL_ERROR_HOST_COMMAND return code: %d\n", ret); + int result = ret - HTOOL_ERROR_HOST_COMMAND_START; + if (result < 0) { + return KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE; + } + if (result == HOTH_RES_SUCCESS) { + return KEY_ROTATION_CMD_SUCCESS; + } + return KEY_ROTATION_ERR_HOTH_BASE + result; +} + static enum key_rotation_err send_key_rotation_request( struct libhoth_device* dev, uint16_t command) { const struct hoth_request_key_rotation_record request = { @@ -40,9 +73,7 @@ static enum key_rotation_err send_key_rotation_request( dev, HOTH_CMD_BOARD_SPECIFIC_BASE + HOTH_PRV_CMD_HAVEN_KEY_ROTATION_OP, 0, &request, sizeof(request), NULL, 0, &rlen); if (ret != 0) { - fprintf(stderr, "HOTH_KEY_ROTATION_COMMAND %d error code: %d\n", command, - ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } if (rlen != 0) { fprintf(stderr, @@ -71,8 +102,7 @@ enum key_rotation_err libhoth_key_rotation_get_version( &rlen); if (ret != 0) { - fprintf(stderr, "HOTH_KEY_ROTATION_GET_VERSION error code: %d\n", ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } if (rlen != sizeof(*record_version)) { @@ -89,6 +119,12 @@ enum key_rotation_err libhoth_key_rotation_get_version( enum key_rotation_err libhoth_key_rotation_get_status( struct libhoth_device* dev, struct hoth_response_key_rotation_status* record_status) { + uint8_t version = 0; + if (get_command_version(dev, HOTH_PRV_CMD_HAVEN_KEY_ROTATION_OP, &version) != + 0) { + fprintf(stderr, "Failed to get command version.\n"); + return KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE; + } const struct hoth_request_key_rotation_record request = { .operation = KEY_ROTATION_RECORD_GET_STATUS, .packet_offset = 0, @@ -102,8 +138,7 @@ enum key_rotation_err libhoth_key_rotation_get_status( &request, sizeof(request), record_status, sizeof(*record_status), &rlen); if (ret != 0) { - fprintf(stderr, "HOTH_KEY_ROTATION_GET_STATUS error code: %d\n", ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } if (rlen != sizeof(*record_status)) { @@ -134,8 +169,7 @@ enum key_rotation_err libhoth_key_rotation_payload_status( &rlen); if (ret != 0) { - fprintf(stderr, "HOTH_KEY_ROTATION_PAYLOAD_STATUS error code: %d\n", ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } if (rlen != sizeof(*payload_status)) { @@ -184,8 +218,7 @@ enum key_rotation_err libhoth_key_rotation_update(struct libhoth_device* dev, 0, &request, sizeof(request.hdr) + request.hdr.packet_size, NULL, 0, &response_length); if (ret != 0) { - fprintf(stderr, "Error code from hoth: %d\n", ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } if (response_length != 0) { fprintf(stderr, "Expected exactly %d response bytes, got %ld\n", 0, @@ -246,8 +279,7 @@ static enum key_rotation_err send_key_rotation_read_helper( &request, sizeof(request.hdr) + request_payload_size, response_data, response_buffer_size, response_length); if (ret != 0) { - fprintf(stderr, "HOTH_KEY_ROTATION_READ error code: %x\n", ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } return KEY_ROTATION_CMD_SUCCESS; } @@ -360,7 +392,7 @@ enum key_rotation_err libhoth_key_rotation_read_chunk_type( fprintf(stderr, "Chunk length invalid: %d Chunk length must be greater than %d\n", chunk_length, STRUCT_CHUNK_SIZE); - return KEY_ROTATION_ERR; + return KEY_ROTATION_INTERNAL_ERR; } if (read_size == 0) { read_size = @@ -399,8 +431,7 @@ enum key_rotation_err libhoth_key_rotation_chunk_type_count( dev, HOTH_CMD_BOARD_SPECIFIC_BASE + HOTH_PRV_CMD_HAVEN_KEY_ROTATION_OP, 0, &request, sizeof(request), &response, sizeof(response), &rlen); if (ret != 0) { - fprintf(stderr, "HOTH_KEY_ROTATION_CHUNK_TYPE_COUNT error code: %d\n", ret); - return KEY_ROTATION_ERR; + return get_key_rotation_error(ret); } if (rlen != sizeof(response)) { fprintf(stderr, diff --git a/protocol/key_rotation.h b/protocol/key_rotation.h index 1604185..7a0df8c 100644 --- a/protocol/key_rotation.h +++ b/protocol/key_rotation.h @@ -15,8 +15,8 @@ #ifndef _LIBHOTH_PROTOCOL_KEY_ROTATION_H_ #define _LIBHOTH_PROTOCOL_KEY_ROTATION_H_ -#include #include +#include #include "protocol/host_cmd.h" #include "transports/libhoth_device.h" @@ -26,6 +26,8 @@ extern "C" { #endif #define HOTH_PRV_CMD_HAVEN_KEY_ROTATION_OP 0x004d +#define HOTH_PRV_CMD_HAVEN_GET_CMD_VERSIONS 0x0008 + #define KEY_ROTATION_HASH_DIGEST_SIZE 32 #define KEY_ROTATION_FLASH_AREA_SIZE 2048 #define KEY_ROTATION_MAX_RECORD_SIZE \ @@ -48,12 +50,13 @@ extern "C" { enum key_rotation_err { KEY_ROTATION_CMD_SUCCESS = 0, - KEY_ROTATION_ERR, + KEY_ROTATION_INTERNAL_ERR, KEY_ROTATION_ERR_INVALID_PARAM, - KEY_ROTATION_ERR_UNIMPLEMENTED, KEY_ROTATION_ERR_INVALID_RESPONSE_SIZE, KEY_ROTATION_INITIATE_FAIL, KEY_ROTATION_COMMIT_FAIL, + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE, + KEY_ROTATION_ERR_HOTH_BASE = 1000, }; enum key_rotation_record_read_half { diff --git a/protocol/key_rotation_test.cc b/protocol/key_rotation_test.cc index 463fba3..5f67142 100644 --- a/protocol/key_rotation_test.cc +++ b/protocol/key_rotation_test.cc @@ -86,7 +86,7 @@ TEST_F(LibHothTest, key_rotation_get_version_failure_io) { struct hoth_response_key_rotation_record_version actual_response; EXPECT_EQ(libhoth_key_rotation_get_version(&hoth_dev_, &actual_response), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, key_rotation_get_version_failure_wrong_size) { @@ -132,7 +132,7 @@ TEST_F(LibHothTest, key_rotation_get_status_failure_io) { struct hoth_response_key_rotation_status actual_status; EXPECT_EQ(libhoth_key_rotation_get_status(&hoth_dev_, &actual_status), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, key_rotation_get_status_failure_wrong_size) { @@ -178,7 +178,7 @@ TEST_F(LibHothTest, key_rotation_payload_status_failure_io) { struct hoth_response_key_rotation_payload_status actual_payload_status; EXPECT_EQ( libhoth_key_rotation_payload_status(&hoth_dev_, &actual_payload_status), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, key_rotation_payload_status_failure_wrong_size) { @@ -281,7 +281,7 @@ TEST_F(LibHothTest, key_rotation_read_failure_io) { EXPECT_EQ(libhoth_key_rotation_read(&hoth_dev_, 0, 8, KEY_ROTATION_RECORD_READ_HALF_ACTIVE, &actual_read_response), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, key_rotation_read_failure_wrong_size) { @@ -333,7 +333,7 @@ TEST_F(LibHothTest, key_rotation_update_failure) { .WillOnce(DoAll(CopyResp(&kDummy, 0), Return(LIBHOTH_OK))) .WillOnce(DoAll(CopyResp(&kDummy, 0), Return(-1))); EXPECT_EQ(libhoth_key_rotation_update(&hoth_dev_, &data[0], sizeof(data)), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, key_rotation_update_initiate_failure) { @@ -373,13 +373,15 @@ TEST_F(LibHothTest, key_rotation_update_failure_invalid_size_too_small) { TEST_F(LibHothTest, key_rotation_update_failure_invalid_response_size) { uint8_t data[100] = {0}; + struct hoth_host_response success_header = {.result = HOTH_RES_SUCCESS}; + EXPECT_CALL(mock_, send(_, UsesCommand(kCmd), _)) .WillRepeatedly(Return(LIBHOTH_OK)); EXPECT_CALL(mock_, receive) - .WillOnce(DoAll(CopyResp(&kDummy, 0), Return(LIBHOTH_OK))) - .WillOnce(DoAll(CopyResp(&kDummy, 2), Return(LIBHOTH_OK))); + .WillOnce(DoAll(CopyResp(&success_header, sizeof(success_header)), + Return(LIBHOTH_OK))); EXPECT_EQ(libhoth_key_rotation_update(&hoth_dev_, &data[0], sizeof(data)), - KEY_ROTATION_ERR); + KEY_ROTATION_INITIATE_FAIL); } TEST_F(LibHothTest, key_rotation_read_chunk_type_success) { @@ -414,7 +416,7 @@ TEST_F(LibHothTest, key_rotation_read_chunk_type_failure_io) { &hoth_dev_, kCmdRotPublicKey, 0, 0, KEY_ROTATION_RECORD_READ_CHUNK_TYPE_MAX_SIZE, &actual_read_response, &response_size), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, key_rotation_read_chunk_type_failure_invalid_size) { @@ -475,7 +477,7 @@ TEST_F(LibHothTest, key_rotation_chunk_type_count_failure_io) { uint16_t chunk_count = 0; EXPECT_EQ(libhoth_key_rotation_chunk_type_count(&hoth_dev_, kCmdRotPublicKey, &chunk_count), - KEY_ROTATION_ERR); + KEY_ROTATION_ROOT_OF_TRUST_UNAVAILABLE); } TEST_F(LibHothTest, diff --git a/protocol/secure_boot_test.cc b/protocol/secure_boot_test.cc index 6973c95..3001461 100644 --- a/protocol/secure_boot_test.cc +++ b/protocol/secure_boot_test.cc @@ -14,12 +14,13 @@ #include "protocol/secure_boot.h" -#include -#include - #include #include "test/libhoth_device_mock.h" +#include +#include +#include "protocol/host_cmd.h" +#include "transports/libhoth_device.h" namespace {