diff --git a/examples/htool_dfu.c b/examples/htool_dfu.c index 6e4c6f0..5f88048 100644 --- a/examples/htool_dfu.c +++ b/examples/htool_dfu.c @@ -47,8 +47,9 @@ static int dfu_update_count(struct opentitan_image_version* desired_romext, struct opentitan_image_version* staged_app = &resp->app.slots[app_stage_slot]; bool booted_needs_update = - !libhoth_ot_version_eq(booted_app, desired_app) || - !libhoth_ot_version_eq(booted_romext, desired_romext); + (libhoth_ot_app_version_cmp_for_update(booted_app, desired_app) != 0) || + (libhoth_ot_rom_ext_version_cmp_for_update(booted_romext, + desired_romext) < 0); if (booted_needs_update) { printf( @@ -58,8 +59,9 @@ static int dfu_update_count(struct opentitan_image_version* desired_romext, } bool staging_needs_update = - !libhoth_ot_version_eq(staged_app, desired_app) || - !libhoth_ot_version_eq(staged_romext, desired_romext); + (libhoth_ot_app_version_cmp_for_update(staged_app, desired_app) != 0) || + (libhoth_ot_rom_ext_version_cmp_for_update(staged_romext, + desired_romext) < 0); if (staging_needs_update) { printf( @@ -152,6 +154,16 @@ int htool_dfu_update(const struct htool_invocation* inv) { goto cleanup2; } + if (!force && (desired_app.security_version < resp.bl0_min_sec_ver)) { + fprintf( + stderr, + "Desired application firmware security version %u is less than " + "currently enforced minimum application firmware security version %u\n", + desired_app.security_version, resp.bl0_min_sec_ver); + retval = -1; + goto cleanup2; + } + int update_cnt = force ? 2 : dfu_update_count(&desired_rom_ext, &desired_app, &resp); @@ -173,7 +185,8 @@ int htool_dfu_update(const struct htool_invocation* inv) { goto cleanup2; } - if (!libhoth_ot_boot_slot_eq(&resp, &desired_rom_ext, &desired_app)) { + if (!libhoth_ot_check_update_successful(&resp, &desired_rom_ext, + &desired_app)) { fprintf(stderr, "Boot slot is wrong after dfu update %d\n", i); libhoth_print_dfu_error(dev, &resp, LIBHOTH_OK); retval = -1; diff --git a/protocol/opentitan_version.c b/protocol/opentitan_version.c index 45fb94d..197734e 100644 --- a/protocol/opentitan_version.c +++ b/protocol/opentitan_version.c @@ -76,17 +76,20 @@ int libhoth_extract_ot_bundle(const uint8_t* image, size_t image_size, static_assert( OPENTITAN_OFFSET_VERSION_MINOR >= OPENTITAN_OFFSET_VERSION_MAJOR, "Version minor offset must be >= major offset"); + static_assert( + OPENTITAN_OFFSET_VERSION_SECURITY >= OPENTITAN_OFFSET_VERSION_MINOR, + "Security version offset must be >= minor version offset"); // Checks that the image offset doesn't cause // the offset calculations to read beyond the image buffer. - if ((offset + OPENTITAN_OFFSET_APP_FW + OPENTITAN_OFFSET_VERSION_MINOR + 4) > - image_size) { + if ((offset + OPENTITAN_OFFSET_APP_FW + OPENTITAN_OFFSET_VERSION_SECURITY + + 4) > image_size) { fprintf(stderr, "Image offset %u is invalid", offset); return -1; } // Checks that the image offset won't overflow the offset calculations - if ((offset + OPENTITAN_OFFSET_APP_FW + OPENTITAN_OFFSET_VERSION_MINOR + 4) < - offset) { + if ((offset + OPENTITAN_OFFSET_APP_FW + OPENTITAN_OFFSET_VERSION_SECURITY + + 4) < offset) { fprintf(stderr, "Image offset %u caused integer overflow", offset); return -1; } @@ -99,6 +102,11 @@ int libhoth_extract_ot_bundle(const uint8_t* image, size_t image_size, image[offset + OPENTITAN_OFFSET_VERSION_MINOR + 1] << 8 | image[offset + OPENTITAN_OFFSET_VERSION_MINOR + 2] << 16 | image[offset + OPENTITAN_OFFSET_VERSION_MINOR + 3] << 24; + rom_ext->security_version = + image[offset + OPENTITAN_OFFSET_VERSION_SECURITY] | + image[offset + OPENTITAN_OFFSET_VERSION_SECURITY + 1] << 8 | + image[offset + OPENTITAN_OFFSET_VERSION_SECURITY + 2] << 16 | + image[offset + OPENTITAN_OFFSET_VERSION_SECURITY + 3] << 24; // Extract the offset that contains the APP version information // We will have the desired APP version be stored on slot index 0 and keep @@ -112,6 +120,11 @@ int libhoth_extract_ot_bundle(const uint8_t* image, size_t image_size, image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR + 1] << 8 | image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR + 2] << 16 | image[offset_app + OPENTITAN_OFFSET_VERSION_MINOR + 3] << 24; + app->security_version = + image[offset_app + OPENTITAN_OFFSET_VERSION_SECURITY] | + image[offset_app + OPENTITAN_OFFSET_VERSION_SECURITY + 1] << 8 | + image[offset_app + OPENTITAN_OFFSET_VERSION_SECURITY + 2] << 16 | + image[offset_app + OPENTITAN_OFFSET_VERSION_SECURITY + 3] << 24; return 0; } @@ -125,6 +138,33 @@ bool libhoth_ot_version_eq(const struct opentitan_image_version* a, } } +int libhoth_ot_app_version_cmp_for_update( + const struct opentitan_image_version* a, + const struct opentitan_image_version* b) { + if (a->major != b->major) { + return (a->major > b->major) ? 1 : -1; + } + if (a->minor != b->minor) { + return (a->minor > b->minor) ? 1 : -1; + } + return 0; +} + +int libhoth_ot_rom_ext_version_cmp_for_update( + const struct opentitan_image_version* a, + const struct opentitan_image_version* b) { + if (a->security_version != b->security_version) { + return (a->security_version > b->security_version) ? 1 : -1; + } + if (a->major != b->major) { + return (a->major > b->major) ? 1 : -1; + } + if (a->minor != b->minor) { + return (a->minor > b->minor) ? 1 : -1; + } + return 0; +} + void libhoth_print_ot_version(const char* prefix, const struct opentitan_image_version* ver) { printf("%s: %d.%d, sv=%d\"\n\"", prefix, ver->major, ver->minor, @@ -211,27 +251,34 @@ const struct opentitan_image_version* libhoth_ot_staged_romext( return &resp->rom_ext.slots[rom_ext_stage_slot]; } -bool libhoth_ot_boot_slot_eq( +bool libhoth_ot_check_update_successful( const struct opentitan_get_version_resp* resp, const struct opentitan_image_version* desired_romext, const struct opentitan_image_version* desired_app) { - return libhoth_ot_version_eq(libhoth_ot_boot_romext(resp), desired_romext) && - libhoth_ot_version_eq(libhoth_ot_boot_app(resp), desired_app); + return (libhoth_ot_app_version_cmp_for_update(libhoth_ot_boot_app(resp), + desired_app) == 0) && + (libhoth_ot_rom_ext_version_cmp_for_update( + libhoth_ot_boot_romext(resp), desired_romext) >= 0); } -bool libhoth_ot_staged_slot_eq( +bool libhoth_ot_check_staged_slot_after_update( const struct opentitan_get_version_resp* resp, const struct opentitan_image_version* desired_romext, const struct opentitan_image_version* desired_app) { - return libhoth_ot_version_eq(libhoth_ot_staged_romext(resp), - desired_romext) && - libhoth_ot_version_eq(libhoth_ot_staged_app(resp), desired_app); + return (libhoth_ot_app_version_cmp_for_update(libhoth_ot_staged_app(resp), + desired_app) == 0) && + // Staged ROM_EXT will be the same version as the firmware update + // package (including the security version) + (libhoth_ot_rom_ext_version_cmp_for_update( + libhoth_ot_staged_romext(resp), desired_romext) == 0); } bool libhoth_update_complete( const struct opentitan_get_version_resp* resp, const struct opentitan_image_version* desired_romext, const struct opentitan_image_version* desired_app) { - return libhoth_ot_boot_slot_eq(resp, desired_romext, desired_app) && - libhoth_ot_staged_slot_eq(resp, desired_romext, desired_app); + return libhoth_ot_check_update_successful(resp, desired_romext, + desired_app) && + libhoth_ot_check_staged_slot_after_update(resp, desired_romext, + desired_app); } diff --git a/protocol/opentitan_version.h b/protocol/opentitan_version.h index aec870f..e5fd5a8 100644 --- a/protocol/opentitan_version.h +++ b/protocol/opentitan_version.h @@ -117,6 +117,23 @@ int libhoth_extract_ot_bundle(const uint8_t* image, size_t image_size, bool libhoth_ot_version_eq(const struct opentitan_image_version* a, const struct opentitan_image_version* b); +// Compare versions of application for firmware update logic. +// Returns a value: +// > 0, if `a` > `b` +// < 0, if `a` < `b` +// = 0, if `a` == `b` +int libhoth_ot_app_version_cmp_for_update( + const struct opentitan_image_version* a, + const struct opentitan_image_version* b); + +// Compare versions of ROM_EXT for firmware update logic. +// Returns a value: +// > 0, if `a` > `b` +// < 0, if `a` < `b` +// = 0, if `a` == `b` +int libhoth_ot_rom_ext_version_cmp_for_update( + const struct opentitan_image_version* a, + const struct opentitan_image_version* b); void libhoth_print_ot_version(const char* prefix, const struct opentitan_image_version* ver); void libhoth_print_ot_version_resp( @@ -132,11 +149,11 @@ const struct opentitan_image_version* libhoth_ot_staged_app( const struct opentitan_get_version_resp* resp); const struct opentitan_image_version* libhoth_ot_staged_romext( const struct opentitan_get_version_resp* resp); -bool libhoth_ot_boot_slot_eq( +bool libhoth_ot_check_update_successful( const struct opentitan_get_version_resp* resp, const struct opentitan_image_version* desired_romext, const struct opentitan_image_version* desired_app); -bool libhoth_ot_staged_slot_eq( +bool libhoth_ot_check_staged_slot_after_update( const struct opentitan_get_version_resp* resp, const struct opentitan_image_version* desired_romext, const struct opentitan_image_version* desired_app); diff --git a/protocol/opentitan_version_test.cc b/protocol/opentitan_version_test.cc index d7e0ead..85df47c 100644 --- a/protocol/opentitan_version_test.cc +++ b/protocol/opentitan_version_test.cc @@ -34,11 +34,16 @@ TEST_F(LibHothTest, opentitan_version_test) { mock_response.rom_ext.slots[0].minor = 123; mock_response.rom_ext.slots[1].major = 0; mock_response.rom_ext.slots[1].minor = 124; + mock_response.rom_ext.booted_slot = kOpentitanBootSlotB; mock_response.app.slots[0].major = 0; mock_response.app.slots[0].minor = 123; mock_response.app.slots[1].major = 0; mock_response.app.slots[1].minor = 124; + mock_response.app.booted_slot = kOpentitanBootSlotA; + + mock_response.bl0_min_sec_ver = 5; + mock_response.primary_bl0_slot = kOpentitanBootSlotB; EXPECT_CALL(mock_, send(_, UsesCommand(HOTH_OPENTITAN_GET_VERSION), _)) .WillOnce(Return(LIBHOTH_OK)); @@ -57,10 +62,16 @@ TEST_F(LibHothTest, opentitan_version_test) { mock_response.rom_ext.slots[1].major); EXPECT_EQ(response.rom_ext.slots[1].minor, mock_response.rom_ext.slots[1].minor); + EXPECT_EQ(response.rom_ext.booted_slot, mock_response.rom_ext.booted_slot); + EXPECT_EQ(response.app.slots[0].major, mock_response.app.slots[0].major); EXPECT_EQ(response.app.slots[0].minor, mock_response.app.slots[0].minor); EXPECT_EQ(response.app.slots[1].major, mock_response.app.slots[1].major); EXPECT_EQ(response.app.slots[1].minor, mock_response.app.slots[1].minor); + EXPECT_EQ(response.app.booted_slot, mock_response.app.booted_slot); + + EXPECT_EQ(response.bl0_min_sec_ver, mock_response.bl0_min_sec_ver); + EXPECT_EQ(response.primary_bl0_slot, mock_response.primary_bl0_slot); } TEST_F(LibHothTest, opentitan_image_version_eq_test) { @@ -81,6 +92,12 @@ TEST_F(LibHothTest, opentitan_image_version_eq_test) { }; EXPECT_TRUE(libhoth_ot_version_eq(&v1, &v2)); + + // Does not care about security version + v1.security_version = 2; + EXPECT_TRUE(libhoth_ot_version_eq(&v1, &v2)); + v1.security_version = v2.security_version; + v1.minor = 4; EXPECT_FALSE(libhoth_ot_version_eq(&v1, &v2)); } @@ -130,8 +147,10 @@ TEST_F(LibHothTest, opentitan_image_compare_test) { resp.rom_ext.slots[0].major = 6; resp.rom_ext.slots[0].minor = 111; + resp.rom_ext.slots[0].security_version = 2; resp.rom_ext.slots[1].major = 7; resp.rom_ext.slots[1].minor = 222; + resp.rom_ext.slots[1].security_version = 2; resp.app.slots[0].major = 8; resp.app.slots[0].minor = 333; @@ -141,20 +160,95 @@ TEST_F(LibHothTest, opentitan_image_compare_test) { resp.rom_ext.booted_slot = kOpentitanBootSlotA; resp.app.booted_slot = kOpentitanBootSlotB; - EXPECT_TRUE(libhoth_ot_boot_slot_eq(&resp, libhoth_ot_boot_romext(&resp), - libhoth_ot_boot_app(&resp))); - EXPECT_FALSE(libhoth_ot_boot_slot_eq(&resp, libhoth_ot_staged_romext(&resp), - libhoth_ot_boot_app(&resp))); - EXPECT_FALSE(libhoth_ot_boot_slot_eq(&resp, libhoth_ot_boot_romext(&resp), - libhoth_ot_staged_app(&resp))); + // Case: Versions match exactly + EXPECT_TRUE(libhoth_ot_check_update_successful( + &resp, libhoth_ot_boot_romext(&resp), libhoth_ot_boot_app(&resp))); + EXPECT_TRUE(libhoth_ot_check_staged_slot_after_update( + &resp, libhoth_ot_staged_romext(&resp), libhoth_ot_staged_app(&resp))); + + // Case: Desired ROM_EXT has greater major version but smaller security + // version + resp.rom_ext.slots[0].major = 6; + resp.rom_ext.slots[0].minor = 111; + resp.rom_ext.slots[0].security_version = 2; + resp.rom_ext.slots[1].major = 7; + resp.rom_ext.slots[1].minor = 111; + resp.rom_ext.slots[1].security_version = 1; - EXPECT_TRUE(libhoth_ot_staged_slot_eq(&resp, libhoth_ot_staged_romext(&resp), - libhoth_ot_staged_app(&resp))); - EXPECT_FALSE(libhoth_ot_staged_slot_eq(&resp, libhoth_ot_boot_romext(&resp), - libhoth_ot_staged_app(&resp))); - EXPECT_FALSE(libhoth_ot_staged_slot_eq(&resp, libhoth_ot_staged_romext(&resp), - libhoth_ot_boot_app(&resp))); + resp.app.slots[0].major = 8; + resp.app.slots[0].minor = 333; + resp.app.slots[1].major = 9; + resp.app.slots[1].minor = 444; + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotB; + + struct opentitan_image_version desired_rom_ext_ver = { + .major = 7, + .minor = 111, + .security_version = 1, + }; + + EXPECT_TRUE(libhoth_ot_check_update_successful(&resp, &desired_rom_ext_ver, + libhoth_ot_boot_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_update_successful( + &resp, &desired_rom_ext_ver, libhoth_ot_staged_app(&resp))); + EXPECT_TRUE(libhoth_ot_check_staged_slot_after_update( + &resp, &desired_rom_ext_ver, libhoth_ot_staged_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_staged_slot_after_update( + &resp, &desired_rom_ext_ver, libhoth_ot_boot_app(&resp))); + + // Assume that ROM_EXT update did not take place for some reason + resp.rom_ext.slots[1].major = 6; + resp.rom_ext.slots[1].minor = 111; + resp.rom_ext.slots[1].security_version = 2; + + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotB; + + EXPECT_TRUE(libhoth_ot_check_update_successful(&resp, &desired_rom_ext_ver, + libhoth_ot_boot_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_update_successful( + &resp, &desired_rom_ext_ver, libhoth_ot_staged_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_staged_slot_after_update( + &resp, &desired_rom_ext_ver, libhoth_ot_staged_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_staged_slot_after_update( + &resp, &desired_rom_ext_ver, libhoth_ot_boot_app(&resp))); + + // Case: Desired ROM_EXT has greater security version but smaller major + // version + resp.rom_ext.slots[0].major = 7; + resp.rom_ext.slots[0].minor = 111; + resp.rom_ext.slots[0].security_version = 2; + resp.rom_ext.slots[1].major = 7; + resp.rom_ext.slots[1].minor = 111; + resp.rom_ext.slots[1].security_version = 2; + + resp.app.slots[0].major = 8; + resp.app.slots[0].minor = 333; + resp.app.slots[1].major = 9; + resp.app.slots[1].minor = 444; + + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotB; + + desired_rom_ext_ver = { + .major = 6, + .minor = 111, + .security_version = 3, + }; + + EXPECT_FALSE(libhoth_ot_check_update_successful(&resp, &desired_rom_ext_ver, + libhoth_ot_boot_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_update_successful( + &resp, &desired_rom_ext_ver, libhoth_ot_staged_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_staged_slot_after_update( + &resp, &desired_rom_ext_ver, libhoth_ot_staged_app(&resp))); + EXPECT_FALSE(libhoth_ot_check_staged_slot_after_update( + &resp, &desired_rom_ext_ver, libhoth_ot_boot_app(&resp))); +} + +TEST_F(LibHothTest, TestLibhothUpdateComplete) { struct opentitan_image_version romext = { .major = 6, .minor = 111, @@ -162,23 +256,145 @@ TEST_F(LibHothTest, opentitan_image_compare_test) { .timestamp = 1234, .measurement = {}, }; + struct opentitan_image_version romext_security_version_larger = { + .major = 5, + .minor = 111, + .security_version = 9, + .timestamp = 1234, + .measurement = {}, + }; + struct opentitan_image_version romext_major_version_larger = { + .major = 8, + .minor = 111, + .security_version = 7, + .timestamp = 1234, + .measurement = {}, + }; + struct opentitan_image_version romext_minor_version_larger = { + .major = 6, + .minor = 114, + .security_version = 7, + .timestamp = 1234, + .measurement = {}, + }; + struct opentitan_image_version romext_minor_version_smaller = { + .major = 6, + .minor = 110, + .security_version = 7, + .timestamp = 1234, + .measurement = {}, + }; - struct opentitan_image_version app = { + struct opentitan_image_version app_1 = { .major = 1, .minor = 116, .security_version = 2, .timestamp = 6789, .measurement = {}, }; + struct opentitan_image_version app_2 = { + .major = 1, + .minor = 115, + .security_version = 2, + .timestamp = 6789, + .measurement = {}, + }; + struct opentitan_get_version_resp resp = {}; + + // Case 1: Successful update of both halves + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; resp.rom_ext.slots[0] = romext; resp.rom_ext.slots[1] = romext; - resp.app.slots[0] = app; - resp.app.slots[1] = app; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + + EXPECT_TRUE(libhoth_update_complete(&resp, &romext, &app_1)); + + // Case 2: Active ROM_EXT did not change since running ROM_EXT had greater + // security version even when desired ROM_EXT had larger major version + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext_security_version_larger; + resp.rom_ext.slots[1] = romext; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_TRUE(libhoth_update_complete(&resp, &romext, &app_1)); + + // Case 3: Active ROM_EXT did not change since running ROM_EXT had greater + // major version + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext_major_version_larger; + resp.rom_ext.slots[1] = romext; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_TRUE(libhoth_update_complete(&resp, &romext, &app_1)); + + // Case 4: Active ROM_EXT did not change since running ROM_EXT had greater + // minor version + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext_minor_version_larger; + resp.rom_ext.slots[1] = romext; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_TRUE(libhoth_update_complete(&resp, &romext, &app_1)); + + // Case 5: ROM_EXT did not change due to some reason (something caused update + // failure) + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext_minor_version_smaller; + resp.rom_ext.slots[1] = romext_minor_version_smaller; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_FALSE(libhoth_update_complete(&resp, &romext, &app_1)); + + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext; + resp.rom_ext.slots[1] = romext; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_FALSE( + libhoth_update_complete(&resp, &romext_security_version_larger, &app_1)); + + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext_security_version_larger; + resp.rom_ext.slots[1] = romext; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_FALSE( + libhoth_update_complete(&resp, &romext_security_version_larger, &app_1)); + + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext; + resp.rom_ext.slots[1] = romext_security_version_larger; + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_1; + EXPECT_FALSE( + libhoth_update_complete(&resp, &romext_security_version_larger, &app_1)); + + // Case 6: Application firmware did not update due to some reason + resp.rom_ext.booted_slot = kOpentitanBootSlotA; + resp.app.booted_slot = kOpentitanBootSlotA; + resp.rom_ext.slots[0] = romext; + resp.rom_ext.slots[1] = romext; + resp.app.slots[0] = app_2; + resp.app.slots[1] = app_2; + EXPECT_FALSE(libhoth_update_complete(&resp, &romext, &app_1)); + + resp.app.slots[0] = app_1; + resp.app.slots[1] = app_2; + EXPECT_FALSE(libhoth_update_complete(&resp, &romext, &app_1)); - EXPECT_TRUE(libhoth_update_complete(&resp, &romext, &app)); - EXPECT_FALSE(libhoth_update_complete(&resp, &romext, &romext)); - EXPECT_FALSE(libhoth_update_complete(&resp, &app, &app)); + resp.app.slots[0] = app_2; + resp.app.slots[1] = app_1; + EXPECT_FALSE(libhoth_update_complete(&resp, &romext, &app_1)); } TEST_F(LibHothTest, ExtractOtBundleBoundsCheckLargeOffset) {