From 62a2a87b1a72391bc609bdabd1e6612101aa6faa Mon Sep 17 00:00:00 2001 From: "pwnh4 (@loicttn)" Date: Thu, 12 Dec 2024 18:29:37 +0100 Subject: [PATCH 1/4] fix(ocv2): missing checks in parsers --- src/handle_finalize.c | 5 + src/kiln_plugin.h | 17 +++ src/provide_parameter/ocv2.c | 240 +++++++++++++++++++++++++++++++++-- 3 files changed, 248 insertions(+), 14 deletions(-) diff --git a/src/handle_finalize.c b/src/handle_finalize.c index 8e84da6..ec415b6 100644 --- a/src/handle_finalize.c +++ b/src/handle_finalize.c @@ -26,6 +26,11 @@ void handle_finalize(ethPluginFinalize_t *msg) { case KILN_V2_MULTICLAIM: case KILN_V2_CLAIM: msg->numScreens = 1; + if (context->next_param != 0) { + PRINTF("Parser did not complete\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } msg->result = ETH_PLUGIN_RESULT_OK; break; diff --git a/src/kiln_plugin.h b/src/kiln_plugin.h index 710b062..4288768 100644 --- a/src/kiln_plugin.h +++ b/src/kiln_plugin.h @@ -46,6 +46,15 @@ typedef enum { KILN_V2_CLAIM, } selector_t; +// **************************************************************************** +// * UTILS +// **************************************************************************** + +typedef struct { + uint8_t prev_checksum[CX_KECCAK_256_SIZE]; + uint32_t new_offset; +} checksum_offset_params_t; + // **************************************************************************** // * GLOBALS // **************************************************************************** @@ -104,11 +113,19 @@ typedef struct { typedef struct { // -- utils + uint16_t cask_ids_offset; + uint16_t current_item_count; } v2_claim_t; typedef struct { // -- utils + uint16_t ticket_ids_offset; + uint16_t cask_ids_offset; + uint8_t checksum_preview[CX_KECCAK_256_SIZE]; + uint8_t checksum_value[CX_KECCAK_256_SIZE]; + uint32_t cached_offset; + uint16_t parent_item_count; uint16_t current_item_count; } v2_multiclaim_t; diff --git a/src/provide_parameter/ocv2.c b/src/provide_parameter/ocv2.c index 6976603..3555298 100644 --- a/src/provide_parameter/ocv2.c +++ b/src/provide_parameter/ocv2.c @@ -72,10 +72,22 @@ void handle_v2_claim(ethPluginProvideParameter_t *msg, context_t *context) { v2_claim_t *params = &context->param_data.v2_claim; switch (context->next_param) { - case V2_CLAIM_TICKET_IDS_OFFSET: + case V2_CLAIM_TICKET_IDS_OFFSET: { + uint16_t offset; + U2BE_from_parameter(msg->parameter, &offset); + if (offset != PARAMETER_LENGTH * 3) { + PRINTF("Malformed calldata, unexpected parameter offset %d != %d\n", + offset, + PARAMETER_LENGTH); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } context->next_param = V2_CLAIM_CASK_IDS_OFFSET; break; + } case V2_CLAIM_CASK_IDS_OFFSET: + U2BE_from_parameter(msg->parameter, ¶ms->cask_ids_offset); + params->cask_ids_offset += SELECTOR_SIZE; context->next_param = V2_CLAIM_MAX_CLAIM_DEPTH; break; case V2_CLAIM_MAX_CLAIM_DEPTH: @@ -86,17 +98,28 @@ void handle_v2_claim(ethPluginProvideParameter_t *msg, context_t *context) { context->next_param = V2_CLAIM_TICKET_IDS__ITEMS; break; case V2_CLAIM_TICKET_IDS__ITEMS: - params->current_item_count -= 1; + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { context->next_param = V2_CLAIM_CASK_IDS_LENGTH; } break; case V2_CLAIM_CASK_IDS_LENGTH: + if (msg->parameterOffset != params->cask_ids_offset) { + PRINTF("Malformed calldata, unexpected parameter offset %d != %d\n", + msg->parameterOffset, + params->cask_ids_offset); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); context->next_param = V2_CLAIM_CASK_IDS__ITEMS; break; case V2_CLAIM_CASK_IDS__ITEMS: - params->current_item_count -= 1; + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { context->next_param = V2_CLAIM_UNEXPECTED_PARAMETER; } @@ -150,13 +173,27 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) v2_multiclaim_t *params = &context->param_data.v2_multiclaim; switch (context->next_param) { - case V2_MULTICLAIM_EXIT_QUEUES_OFFSET: + case V2_MULTICLAIM_EXIT_QUEUES_OFFSET: { + uint16_t offset; + U2BE_from_parameter(msg->parameter, &offset); + if (offset != PARAMETER_LENGTH * 3) { + PRINTF("Malformed calldata, unexpected exitqueues parameter offset %d != %d\n", + offset, + PARAMETER_LENGTH); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } context->next_param = V2_MULTICLAIM_TICKET_IDS_OFFSET; break; + } case V2_MULTICLAIM_TICKET_IDS_OFFSET: + U2BE_from_parameter(msg->parameter, ¶ms->ticket_ids_offset); + params->ticket_ids_offset += SELECTOR_SIZE; context->next_param = V2_MULTICLAIM_CASK_IDS_OFFSET; break; case V2_MULTICLAIM_CASK_IDS_OFFSET: + U2BE_from_parameter(msg->parameter, ¶ms->cask_ids_offset); + params->cask_ids_offset += SELECTOR_SIZE; context->next_param = V2_MULTICLAIM_EXIT_QUEUES_LENGTH; break; case V2_MULTICLAIM_EXIT_QUEUES_LENGTH: @@ -183,57 +220,232 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) return; } - params->current_item_count -= 1; + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { context->next_param = V2_MULTICLAIM_TICKETIDS_LENGTH; } break; } case V2_MULTICLAIM_TICKETIDS_LENGTH: + if (msg->parameterOffset != params->ticket_ids_offset) { + PRINTF("Malformed calldata, unexpected ticketids[X][] parameter offset %d != %d\n", + msg->parameterOffset, + params->ticket_ids_offset); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + memset(params->checksum_preview, 0, sizeof(params->checksum_preview)); + memset(params->checksum_value, 0, sizeof(params->checksum_value)); + params->cached_offset = 0; + U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); params->current_item_count = params->parent_item_count; + context->next_param = V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS; break; - case V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS: - params->current_item_count -= 1; + // ******************************************************************** + // TICKETIDS[][] + // ******************************************************************** + case V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS: { + uint16_t offset; + U2BE_from_parameter(msg->parameter, &offset); + // We have limited size on the context and can't store all the offset values + // of the ticketids subarrays. So we compute their checksum and expect to + // be able to recompute it using the offset of the parsed structures later. + // _preview will be equal to _value at the end of the parsing if everything is fine + checksum_offset_params_t h_params; + memset(&h_params, 0, sizeof(h_params)); + memcpy(&h_params.prev_checksum, + &(params->checksum_preview), + sizeof(h_params.prev_checksum)); + + // if we are on the first element of the array, we save the offset, which all + // received offset values will be based on for checksum computation + if (params->cached_offset == 0) { + params->cached_offset = msg->parameterOffset; + } + + // we hash the previous checksum with the offset of the beginning of the structure. + h_params.new_offset = offset + params->cached_offset; + PRINTF("V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS_PREVIEW: %d\n", h_params.new_offset); + + if (cx_keccak_256_hash((void *) &h_params, + sizeof(h_params), + params->checksum_preview) != CX_OK) { + PRINTF("unable to compute keccak hash\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH; } break; - case V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH: + } + // ******************************************************************** + // TICKETIDS[][] + // . ^ + // ******************************************************************** + case V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH: { + // here we compute the offset of the ticketIds subarray checksum + checksum_offset_params_t h_params; + memset(&h_params, 0, sizeof(h_params)); + memcpy(&h_params.prev_checksum, + &(params->checksum_value), + sizeof(h_params.prev_checksum)); + + // we hash the previous checksum with the offset of the beginning of the structure. + h_params.new_offset = msg->parameterOffset; + PRINTF("V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS_VALUE: %d\n", h_params.new_offset); + + if (cx_keccak_256_hash((void *) &h_params, sizeof(h_params), params->checksum_value) != + CX_OK) { + PRINTF("unable to compute keccak hash\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS; break; + } case V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS: - params->current_item_count -= 1; + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { - params->parent_item_count -= 1; + if (params->parent_item_count > 0) { + params->parent_item_count -= 1; + } if (params->parent_item_count == 0) { + // we check the checksums + if (memcmp(params->checksum_preview, + params->checksum_value, + sizeof(params->checksum_preview)) != 0) { + PRINTF("Tokenids[][] checksums do not match\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + context->next_param = V2_MULTICLAIM_CASKIDS_LENGTH; + } else { context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH; } } break; + // ******************************************************************** + // CASKIDS[][] + // ******************************************************************** case V2_MULTICLAIM_CASKIDS_LENGTH: + if (msg->parameterOffset != params->cask_ids_offset) { + PRINTF("Malformed calldata, unexpected caskids parameter offset %d != %d\n", + msg->parameterOffset, + params->cask_ids_offset); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + memset(params->checksum_preview, 0, sizeof(params->checksum_preview)); + memset(params->checksum_value, 0, sizeof(params->checksum_value)); + params->cached_offset = 0; + U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); params->current_item_count = params->parent_item_count; context->next_param = V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS; break; - case V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS: - params->current_item_count -= 1; + case V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS: { + uint16_t offset; + U2BE_from_parameter(msg->parameter, &offset); + // We have limited size on the context and can't store all the offset values + // of the caskids subarrays. So we compute their checksum and expect to + // be able to recompute it using the offset of the parsed structures later. + // _preview will be equal to _value at the end of the parsing if everything is fine + checksum_offset_params_t h_params; + memset(&h_params, 0, sizeof(h_params)); + memcpy(&h_params.prev_checksum, + &(params->checksum_preview), + sizeof(h_params.prev_checksum)); + + // if we are on the first element of the array, we save the offset, which all + // received offset values will be based on for checksum computation + if (params->cached_offset == 0) { + params->cached_offset = msg->parameterOffset; + } + + // we hash the previous checksum with the offset of the beginning of the structure. + h_params.new_offset = offset + params->cached_offset; + PRINTF("V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS_PREVIEW: %d\n", h_params.new_offset); + + if (cx_keccak_256_hash((void *) &h_params, + sizeof(h_params), + params->checksum_preview) != CX_OK) { + PRINTF("unable to compute keccak hash\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { context->next_param = V2_MULTICLAIM_CASKIDS__ITEM_LENGTH; } break; - case V2_MULTICLAIM_CASKIDS__ITEM_LENGTH: + } + // ******************************************************************** + // CASKIDS[][] + // . ^ + // ******************************************************************** + case V2_MULTICLAIM_CASKIDS__ITEM_LENGTH: { + // here we compute the offset of the caskIds subarray checksum + checksum_offset_params_t h_params; + + memset(&h_params, 0, sizeof(h_params)); + memcpy(&h_params.prev_checksum, + &(params->checksum_value), + sizeof(h_params.prev_checksum)); + + // we hash the previous checksum with the offset of the beginning of the structure. + h_params.new_offset = msg->parameterOffset; + PRINTF("V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS_VALUE: %d\n", h_params.new_offset); + + if (cx_keccak_256_hash((void *) &h_params, sizeof(h_params), params->checksum_value) != + CX_OK) { + PRINTF("unable to compute keccak hash\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); context->next_param = V2_MULTICLAIM_CASKIDS__ITEM__ITEMS; break; + } case V2_MULTICLAIM_CASKIDS__ITEM__ITEMS: - params->current_item_count -= 1; + if (params->current_item_count > 0) { + params->current_item_count -= 1; + } if (params->current_item_count == 0) { + if (params->parent_item_count > 0) { + params->parent_item_count -= 1; + } + if (params->parent_item_count == 0) { + // we check the checksums + if (memcmp(params->checksum_preview, + params->checksum_value, + sizeof(params->checksum_preview)) != 0) { + PRINTF("Caskids[][] checksums do not match\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + context->next_param = V2_MULTICLAIM_UNEXPECTED_PARAMETER; } else { context->next_param = V2_MULTICLAIM_CASKIDS__ITEM_LENGTH; From ca2170dc82a5cc4b6ea10e449c120ba319016e6b Mon Sep 17 00:00:00 2001 From: "pwnh4 (@loicttn)" Date: Fri, 13 Dec 2024 16:09:04 +0100 Subject: [PATCH 2/4] fix(ocv2): bad index jumps --- src/provide_parameter/ocv2.c | 43 +++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/provide_parameter/ocv2.c b/src/provide_parameter/ocv2.c index 3555298..6e744ff 100644 --- a/src/provide_parameter/ocv2.c +++ b/src/provide_parameter/ocv2.c @@ -95,7 +95,11 @@ void handle_v2_claim(ethPluginProvideParameter_t *msg, context_t *context) { break; case V2_CLAIM_TICKET_IDS_LENGTH: U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); - context->next_param = V2_CLAIM_TICKET_IDS__ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_CLAIM_CASK_IDS_LENGTH; + } else { + context->next_param = V2_CLAIM_TICKET_IDS__ITEMS; + } break; case V2_CLAIM_TICKET_IDS__ITEMS: if (params->current_item_count > 0) { @@ -114,7 +118,11 @@ void handle_v2_claim(ethPluginProvideParameter_t *msg, context_t *context) { return; } U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); - context->next_param = V2_CLAIM_CASK_IDS__ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_CLAIM_UNEXPECTED_PARAMETER; + } else { + context->next_param = V2_CLAIM_CASK_IDS__ITEMS; + } break; case V2_CLAIM_CASK_IDS__ITEMS: if (params->current_item_count > 0) { @@ -198,7 +206,11 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) break; case V2_MULTICLAIM_EXIT_QUEUES_LENGTH: U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); - context->next_param = V2_MULTICLAIM_EXIT_QUEUES__ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_TICKETIDS_LENGTH; + } else { + context->next_param = V2_MULTICLAIM_EXIT_QUEUES__ITEMS; + } break; case V2_MULTICLAIM_EXIT_QUEUES__ITEMS: { uint8_t buffer[ADDRESS_LENGTH]; @@ -243,8 +255,11 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); params->current_item_count = params->parent_item_count; - - context->next_param = V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH; + } else { + context->next_param = V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS; + } break; // ******************************************************************** // TICKETIDS[][] @@ -312,7 +327,11 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) } U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); - context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_CASKIDS_LENGTH; + } else { + context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS; + } break; } case V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS: @@ -358,7 +377,11 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); params->current_item_count = params->parent_item_count; - context->next_param = V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_CASKIDS__ITEM_LENGTH; + } else { + context->next_param = V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS; + } break; case V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS: { uint16_t offset; @@ -424,7 +447,11 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) } U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); - context->next_param = V2_MULTICLAIM_CASKIDS__ITEM__ITEMS; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_UNEXPECTED_PARAMETER; + } else { + context->next_param = V2_MULTICLAIM_CASKIDS__ITEM__ITEMS; + } break; } case V2_MULTICLAIM_CASKIDS__ITEM__ITEMS: From b3f91f03a37e881966801c01d811294326a2f63b Mon Sep 17 00:00:00 2001 From: "pwnh4 (@loicttn)" Date: Fri, 13 Dec 2024 16:31:35 +0100 Subject: [PATCH 3/4] fix(ocv2): getEthDisplayableAddress buffer size / timeout issue --- src/provide_parameter/ocv2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/provide_parameter/ocv2.c b/src/provide_parameter/ocv2.c index 6e744ff..8656aec 100644 --- a/src/provide_parameter/ocv2.c +++ b/src/provide_parameter/ocv2.c @@ -215,7 +215,7 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) case V2_MULTICLAIM_EXIT_QUEUES__ITEMS: { uint8_t buffer[ADDRESS_LENGTH]; copy_address(buffer, msg->parameter, sizeof(buffer)); - char address_buffer[ADDRESS_STR_LEN]; + char address_buffer[ADDRESS_STR_LEN + 1]; getEthDisplayableAddress(buffer, address_buffer, sizeof(address_buffer), 0); // we add a check to make sure we know the exit queue addresses // that will be called in the multiclaim tx From 3121f057f1c45a85aebb29f312ffd23943cb1bdf Mon Sep 17 00:00:00 2001 From: "pwnh4 (@loicttn)" Date: Mon, 16 Dec 2024 11:43:56 +0100 Subject: [PATCH 4/4] fix(ocv2): invalid parser state transition when empty arrays --- src/provide_parameter/ocv2.c | 37 ++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/provide_parameter/ocv2.c b/src/provide_parameter/ocv2.c index 8656aec..5dc5698 100644 --- a/src/provide_parameter/ocv2.c +++ b/src/provide_parameter/ocv2.c @@ -256,7 +256,7 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); params->current_item_count = params->parent_item_count; if (params->current_item_count == 0) { - context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH; + context->next_param = V2_MULTICLAIM_CASKIDS_LENGTH; } else { context->next_param = V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS; } @@ -328,7 +328,21 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); if (params->current_item_count == 0) { - context->next_param = V2_MULTICLAIM_CASKIDS_LENGTH; + if (params->parent_item_count > 0) { + params->parent_item_count -= 1; + } + if (params->parent_item_count == 0) { + // we check the checksums + if (memcmp(params->checksum_preview, + params->checksum_value, + sizeof(params->checksum_preview)) != 0) { + PRINTF("Tokenids[][] checksums do not match\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + context->next_param = V2_MULTICLAIM_CASKIDS_LENGTH; + } } else { context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS; } @@ -378,7 +392,7 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); params->current_item_count = params->parent_item_count; if (params->current_item_count == 0) { - context->next_param = V2_MULTICLAIM_CASKIDS__ITEM_LENGTH; + context->next_param = V2_MULTICLAIM_UNEXPECTED_PARAMETER; } else { context->next_param = V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS; } @@ -448,7 +462,22 @@ void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); if (params->current_item_count == 0) { - context->next_param = V2_MULTICLAIM_UNEXPECTED_PARAMETER; + if (params->parent_item_count > 0) { + params->parent_item_count -= 1; + } + + if (params->parent_item_count == 0) { + // we check the checksums + if (memcmp(params->checksum_preview, + params->checksum_value, + sizeof(params->checksum_preview)) != 0) { + PRINTF("Caskids[][] checksums do not match\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + context->next_param = V2_MULTICLAIM_UNEXPECTED_PARAMETER; + } } else { context->next_param = V2_MULTICLAIM_CASKIDS__ITEM__ITEMS; }