From 5e7604595edf719924333ae646c29b2e39f4184a Mon Sep 17 00:00:00 2001 From: nir Date: Sun, 15 Oct 2023 15:43:42 +0300 Subject: [PATCH] tssForIOS15 --- src/dfu.c | 27 +++++++--- src/img4.c | 33 +----------- src/recovery.c | 14 ++++- src/restore.c | 135 ++++++++++++++++++++++++++++++++++++++++++++----- src/tss.c | 15 ++++-- 5 files changed, 169 insertions(+), 55 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index df6f2928..51c85ab0 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -350,11 +350,13 @@ int dfu_send_iboot_stage1_components(struct idevicerestore_client_t* client, pli uint8_t b = 0; plist_get_bool_val(iboot_node, &b); if (b) { - debug("DEBUG: %s is loaded by iBoot Stage 1.\n", key); - if (dfu_send_component_and_command(client, build_identity, key, "firmware") < 0) { - error("ERROR: Unable to send component '%s' to device.\n", key); - err++; - } + debug("DEBUG: %s is loaded by iBoot Stage 1 and iBoot.\n", key); + } else { + debug("DEBUG: %s is loaded by iBoot Stage 1 but not iBoot...\n", key); + } + if (dfu_send_component_and_command(client, build_identity, key, "firmware") < 0) { + error("ERROR: Unable to send component '%s' to device.\n", key); + err++; } } free(key); @@ -481,7 +483,20 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide client->dfu->client = NULL; return -1; } - + char *value = NULL; + unsigned long boot_stage = 0; + irecv_getenv(client->dfu->client, "boot-stage", &value); + if (value) { + boot_stage = strtoul(value, NULL, 0); + } + if (boot_stage > 0) { + info("iBoot boot-stage=%s\n", value); + free(value); + value = NULL; + if (boot_stage != 1) { + error("ERROR: iBoot should be at boot stage 1, continuing anyway...\n"); + } + } if (dfu_send_iboot_stage1_components(client, build_identity) < 0) { mutex_unlock(&client->device_event_mutex); error("ERROR: Unable to send iBoot stage 1 components to device\n"); diff --git a/src/img4.c b/src/img4.c index 342a8506..9325180a 100644 --- a/src/img4.c +++ b/src/img4.c @@ -305,6 +305,8 @@ static const char *_img4_get_component_tag(const char *compname) { "Ap,VolumeUUID", "vuid" }, { "Ap,rOSLogo1", "rlg1" }, { "Ap,rOSLogo2", "rlg2" }, + { "Ap,SecurePageTableMonitor", "sptm" }, + { "Ap,TrustedExecutionMonitor", "txm" }, { "AppleLogo", "logo" }, { "AudioCodecFirmware", "acfw" }, { "BatteryCharging", "glyC" }, @@ -394,37 +396,6 @@ static const char *_img4_get_component_tag(const char *compname) return NULL; } -static void hexdump(char* data, int length) -{ - int i; - int j; - unsigned char c; - - for (i = 0; i < length; i += 16) { - fprintf(stderr, "%04x: ", i); - for (j = 0; j < 16; j++) { - if (i + j >= length) { - fprintf(stderr, " "); - continue; - } - fprintf(stderr, "%02x ", *(data + i + j) & 0xff); - } - fprintf(stderr, " | "); - for (j = 0; j < 16; j++) { - if (i + j >= length) - break; - c = *(data + i + j); - if ((c < 32) || (c > 127)) { - fprintf(stderr, "."); - continue; - } - fprintf(stderr, "%c", c); - } - fprintf(stderr, "\n"); - } - fprintf(stderr, "\n"); -} - int img4_stitch_component(const char* component_name, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** img4_data, unsigned int *img4_size) { unsigned char* magic_header = NULL; diff --git a/src/recovery.c b/src/recovery.c index 95c99eec..432530f2 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -157,7 +157,19 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build info("iBoot build-style=%s\n", (value) ? value : "(unknown)"); free(value); value = NULL; - + unsigned long boot_stage = 0; + irecv_getenv(client->recovery->client, "boot-stage", &value); + if (value) { + boot_stage = strtoul(value, NULL, 0); + } + if (boot_stage > 0) { + info("iBoot boot-stage=%s\n", value); + free(value); + value = NULL; + if (boot_stage != 2) { + error("ERROR: iBoot should be at boot stage 2, continuing anyway...\n"); + } + } unsigned long radio_error = 0; irecv_getenv(client->recovery->client, "radio-error", &value); if (value) { diff --git a/src/restore.c b/src/restore.c index 5c258aaa..9d419b7e 100644 --- a/src/restore.c +++ b/src/restore.c @@ -742,6 +742,7 @@ int restore_handle_status_msg(restored_client_t client, plist_t msg) case 27: info("Status: Failed to mount filesystems.\n"); break; + case 50: case 51: info("Status: Failed to load SEP Firmware.\n"); break; @@ -1378,7 +1379,30 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* personalized_data = NULL; personalized_size = 0; } + if (build_identity_has_component(build_identity, "SepStage1") && + build_identity_get_component_path(build_identity, "SepStage1", &sep_path) == 0) { + component = "SepStage1"; + ret = extract_component(client->ipsw, sep_path, &component_data, &component_size); + free(sep_path); + if (ret < 0) { + error("ERROR: Unable to extract component: %s\n", component); + return -1; + } + ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); + free(component_data); + component_data = NULL; + component_size = 0; + if (ret < 0) { + error("ERROR: Unable to get personalized component: %s\n", component); + return -1; + } + + plist_dict_set_item(dict, "SEPPatchImageData", plist_new_data((char*)personalized_data, (uint64_t) personalized_size)); + free(personalized_data); + personalized_data = NULL; + personalized_size = 0; + } if (idevicerestore_debug) debug_plist(dict); @@ -2105,7 +2129,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest return 0; } -static plist_t restore_get_se_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_se_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) { const char *comp_name = NULL; char *comp_path = NULL; @@ -2114,6 +2138,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id plist_t parameters = NULL; plist_t request = NULL; plist_t response = NULL; + plist_t p_dgr = NULL; int ret; uint64_t chip_id = 0; plist_t node = plist_dict_get_item(p_info, "SE,ChipID"); @@ -2122,7 +2147,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id } if (chip_id == 0x20211) { comp_name = "SE,Firmware"; - } else if (chip_id == 0x73 || chip_id == 0x64 || chip_id == 0xC8 || chip_id == 0xD2) { + } else if (chip_id == 0x73 || chip_id == 0x64 || chip_id == 0xC8 || chip_id == 0xD2 || chip_id == 0x2C) { comp_name = "SE,UpdatePayload"; } else { info("WARNING: Unknown SE,ChipID 0x%" PRIx64 " detected. Restore might fail.\n", (uint64_t)chip_id); @@ -2136,6 +2161,13 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id } debug("DEBUG: %s: using %s\n", __func__, comp_name); } + p_dgr = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (!p_dgr) { + info("NOTE: %s: No DeviceGeneratedRequest in firmware updater data request. Continuing anyway.\n", __func__); + } else if (!PLIST_IS_DICT(p_dgr)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); @@ -2167,7 +2199,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id plist_dict_merge(¶meters, p_info); /* add required tags for SE TSS request */ - tss_request_add_se_tags(request, parameters, NULL); + tss_request_add_se_tags(request, parameters, p_dgr); plist_free(parameters); @@ -2180,10 +2212,12 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id return NULL; } - if (plist_dict_get_item(response, "SE,Ticket")) { - info("Received SE ticket\n"); + if (plist_dict_get_item(response, "SE2,Ticket")) { + info("Received SE2,Ticket\n"); + } else if (plist_dict_get_item(response, "SE,Ticket")) { + info("Received SE,Ticket\n"); } else { - error("ERROR: No 'SE,Ticket' in TSS response, this might not work\n"); + error("ERROR: No 'SE ticket' in TSS response, this might not work\n"); } plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, (uint64_t) component_size)); @@ -2369,7 +2403,7 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru return response; } -static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) { char *comp_name = NULL; char *comp_path = NULL; @@ -2404,8 +2438,14 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(0)); } - /* add Rap,* tags from info dictionary to parameters */ - plist_dict_merge(¶meters, p_info); + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request) { + /* use DeviceGeneratedRequest if present */ + plist_dict_merge(&request, device_generated_request); + } else { + /* add Rap,* tags from info dictionary to parameters */ + plist_dict_merge(¶meters, p_info); + } /* add required tags for Rose TSS request */ tss_request_add_rose_tags(request, parameters, NULL); @@ -2426,7 +2466,11 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct } else { error("ERROR: No 'Rap,Ticket' in TSS response, this might not work\n"); } - + /* skip FirmwareData for newer versions */ + if (client->build_major >= 20) { + debug("DEBUG: Not adding FirmwareData.\n"); + return response; + } comp_name = "Rap,RTKitOS"; if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); @@ -2599,7 +2643,60 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str return response; } +static plist_t restore_get_generic_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) +{ + plist_t request = NULL; + plist_t response = NULL; + + plist_t p_updater_name = plist_dict_get_item(arguments, "MessageArgUpdaterName"); + const char* s_updater_name = plist_get_string_ptr(p_updater_name, NULL); + plist_t response_tags = plist_access_path(arguments, 2, "DeviceGeneratedTags", "ResponseTags"); + const char* response_ticket = NULL; + if (PLIST_IS_ARRAY(response_tags)) { + plist_t tag0 = plist_array_get_item(response_tags, 0); + if (tag0) { + response_ticket = plist_get_string_ptr(tag0, NULL); + } + } + if (response_ticket == NULL) { + error("ERROR: Unable to determine response ticket from device generated tags"); + return NULL; + } + + /* create TSS request */ + request = tss_request_new(NULL); + if (request == NULL) { + error("ERROR: Unable to create %s TSS request\n", s_updater_name); + return NULL; + } + + /* add device generated request data to request */ + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (!device_generated_request) { + error("ERROR: Could not find DeviceGeneratedRequest in arguments dictionary\n"); + plist_free(request); + return NULL; + } + plist_dict_merge(&request, device_generated_request); + + info("Sending %s TSS request...\n", s_updater_name); + response = tss_request_send(request, client->tss_url); + plist_free(request); + if (response == NULL) { + error("ERROR: Unable to fetch %s ticket\n", s_updater_name); + return NULL; + } + + if (plist_dict_get_item(response, response_ticket)) { + info("Received %s\n", response_ticket); + } else { + error("ERROR: No '%s' in TSS response, this might not work\n", response_ticket); + debug_plist(response); + } + + return response; +} static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) { char *comp_name = "Baobab,TCON"; @@ -3025,7 +3122,7 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct plist_get_string_val(p_updater_name, &s_updater_name); if (strcmp(s_updater_name, "SE") == 0) { - fwdict = restore_get_se_firmware_data(restore, client, build_identity, p_info); + fwdict = restore_get_se_firmware_data(restore, client, build_identity, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get SE firmware data\n", __func__); goto error_out; @@ -3044,7 +3141,7 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct goto error_out; } } else if (strcmp(s_updater_name, "Rose") == 0) { - fwdict = restore_get_rose_firmware_data(restore, client, build_identity, p_info); + fwdict = restore_get_rose_firmware_data(restore, client, build_identity, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get Rose firmware data\n", __func__); goto error_out; @@ -3061,6 +3158,12 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct error("ERROR: %s: Couldn't get AppleTCON firmware data\n", __func__); goto error_out; } + } else if (strcmp(s_updater_name, "PS190") == 0) { + fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments); + if (fwdict == NULL) { + error("ERROR: %s: Couldn't get PCON1 firmware data\n", __func__); + goto error_out; + } } else if (strcmp(s_updater_name, "AppleTypeCRetimer") == 0) { fwdict = restore_get_timer_firmware_data(restore, client, build_identity, p_info); if (fwdict == NULL) { @@ -3074,8 +3177,12 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct goto error_out; } } else { - error("ERROR: %s: Got unknown updater name '%s'.\n", __func__, s_updater_name); - goto error_out; + error("ERROR: %s: Got unknown updater name '%s', trying to discover from device generated request.\n", __func__, s_updater_name); + fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments); + if (fwdict == NULL) { + error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); + goto error_out; + } } free(s_updater_name); s_updater_name = NULL; diff --git a/src/tss.c b/src/tss.c index 8e0b4bb7..ac81dc3e 100644 --- a/src/tss.c +++ b/src/tss.c @@ -305,6 +305,13 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) plist_dict_set_item(request, "UID_MODE", plist_new_bool(0)); } +// FIXME: I didn't understand yet when this value is set, so for now we use a workaround + if (plist_dict_get_item(parameters, "ApSikaFuse")) { + _plist_dict_copy_item(request, parameters, "Ap,SikaFuse", "ApSikaFuse"); + } else if (_plist_dict_get_bool(parameters, "RequiresUIDMode")) { + // Workaround: We have only seen Ap,SikaFuse together with UID_MODE + plist_dict_set_item(request, "Ap,SikaFuse", plist_new_uint(0)); + } return 0; } @@ -786,9 +793,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid return -1; } - /* add tags indicating we want to get the SE,Ticket */ plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@SE,Ticket", plist_new_bool(1)); if (_plist_dict_copy_uint(request, parameters, "SE,ChipID", NULL) < 0) { error("ERROR: %s: Unable to find required SE,ChipID in parameters\n", __func__); @@ -863,7 +868,10 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid if (overrides) { plist_dict_merge(&request, overrides); } - + /* fallback in case no @SE2,Ticket or @SE,Ticket was provided */ + if (!plist_dict_get_item(request, "@SE2,Ticket") && !plist_dict_get_item(request, "@SE,Ticket")) { + plist_dict_set_item(request, "@SE,Ticket", plist_new_bool(1)); + } return 0; } @@ -1157,6 +1165,7 @@ int tss_request_add_rose_tags(plist_t request, plist_t parameters, plist_t overr _plist_dict_copy_bool(request, parameters, "Rap,ProductionMode", NULL); _plist_dict_copy_uint(request, parameters, "Rap,SecurityDomain", NULL); _plist_dict_copy_bool(request, parameters, "Rap,SecurityMode", NULL); + _plist_dict_copy_data(request, parameters, "Rap,FdrRootCaDigest", NULL); char *comp_name = NULL; plist_dict_iter iter = NULL;