From 1ea3fe75906d360c1f2ac9e6590d5b64f596f0e0 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sun, 26 Sep 2021 14:29:36 +0900 Subject: restore: Add support for updating AppleTCON Closes: #442 Co-authored-by: Nikias Bassen Signed-off-by: Hector Martin --- src/restore.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ src/tss.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tss.h | 1 + 3 files changed, 186 insertions(+) (limited to 'src') diff --git a/src/restore.c b/src/restore.c index 69e5191..b1089bf 100644 --- a/src/restore.c +++ b/src/restore.c @@ -107,6 +107,7 @@ #define INSTALLING_RECOVERY_OS_IMAGE 71 #define REQUESTING_EAN_DATA 74 #define SEALING_SYSTEM_VOLUME 77 +#define UPDATING_APPLETCON 81 static int restore_finished = 0; @@ -625,6 +626,8 @@ const char* restore_progress_string(unsigned int operation) return "Requesting EAN Data"; case SEALING_SYSTEM_VOLUME: return "Sealing System Volume"; + case UPDATING_APPLETCON: + return "Updating AppleTCON"; default: return "Unknown operation"; } @@ -2602,6 +2605,77 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str 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"; + char *comp_path = NULL; + plist_t comp_node = NULL; + unsigned char* component_data = NULL; + unsigned int component_size = 0; + plist_t parameters = NULL; + plist_t request = NULL; + plist_t response = NULL; + plist_t node = NULL; + int ret; + + /* create Baobab request */ + request = tss_request_new(NULL); + if (request == NULL) { + error("ERROR: Unable to create Baobab TSS request\n"); + free(component_data); + return NULL; + } + + parameters = plist_new_dict(); + + /* add manifest for current build_identity to parameters */ + tss_parameters_add_from_manifest(parameters, build_identity); + + /* add Baobab,* tags from info dictionary to parameters */ + plist_dict_merge(¶meters, p_info); + + /* add required tags for Baobab TSS request */ + tss_request_add_tcon_tags(request, parameters, NULL); + + plist_free(parameters); + + info("Sending Baobab TSS request...\n"); + response = tss_request_send(request, client->tss_url); + plist_free(request); + if (response == NULL) { + error("ERROR: Unable to fetch Baobab ticket\n"); + free(component_data); + return NULL; + } + + if (plist_dict_get_item(response, "Baobab,Ticket")) { + info("Received Baobab ticket\n"); + } else { + error("ERROR: No 'Baobab,Ticket' in TSS response, this might not work\n"); + } + + 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); + return NULL; + } + + /* now get actual component data */ + ret = extract_component(client->ipsw, comp_path, &component_data, &component_size); + free(comp_path); + comp_path = NULL; + if (ret < 0) { + error("ERROR: Unable to extract '%s' component\n", comp_name); + return NULL; + } + + plist_dict_set_item(response, "FirmwareData", plist_new_data((char *)component_data, (uint64_t)component_size)); + free(component_data); + component_data = NULL; + component_size = 0; + + return response; +} + static int restore_send_firmware_updater_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) { plist_t arguments; @@ -2689,6 +2763,12 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct error("ERROR: %s: Couldn't get Veridian firmware data\n", __func__); goto error_out; } + } else if (strcmp(s_updater_name, "AppleTCON") == 0) { + fwdict = restore_get_tcon_firmware_data(restore, client, build_identity, p_info); + if (fwdict == NULL) { + error("ERROR: %s: Couldn't get AppleTCON firmware data\n", __func__); + goto error_out; + } } else { error("ERROR: %s: Got unknown updater name '%s'.\n", __func__, s_updater_name); goto error_out; diff --git a/src/tss.c b/src/tss.c index 069e5ed..078d55b 100644 --- a/src/tss.c +++ b/src/tss.c @@ -443,6 +443,34 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) } node = NULL; + /* add Baobab,BoardID */ + node = plist_dict_get_item(build_identity, "Baobab,BoardID"); + if (node) { + plist_dict_set_item(parameters, "Baobab,BoardID", plist_copy(node)); + } + node = NULL; + + /* add Baobab,ChipID */ + node = plist_dict_get_item(build_identity, "Baobab,ChipID"); + if (node) { + plist_dict_set_item(parameters, "Baobab,ChipID", plist_copy(node)); + } + node = NULL; + + /* add Baobab,ManifestEpoch */ + node = plist_dict_get_item(build_identity, "Baobab,ManifestEpoch"); + if (node) { + plist_dict_set_item(parameters, "Baobab,ManifestEpoch", plist_copy(node)); + } + node = NULL; + + /* add Baobab,SecurityDomain */ + node = plist_dict_get_item(build_identity, "Baobab,SecurityDomain"); + if (node) { + plist_dict_set_item(parameters, "Baobab,SecurityDomain", plist_copy(node)); + } + node = NULL; + /* add eUICC,ChipID */ node = plist_dict_get_item(build_identity, "eUICC,ChipID"); if (node) { @@ -1699,6 +1727,83 @@ int tss_request_add_veridian_tags(plist_t request, plist_t parameters, plist_t o return 0; } +int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overrides) +{ + plist_t node = NULL; + + plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); + if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + return -1; + } + + /* add tags indicating we want to get the Rap,Ticket */ + plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); + plist_dict_set_item(request, "@Baobab,Ticket", plist_new_bool(1)); + + uint64_t u64val = 0; + uint8_t bval = 0; + uint8_t isprod = 0; + + u64val = _plist_dict_get_uint(parameters, "Baobab,BoardID"); + plist_dict_set_item(request, "Baobab,BoardID", plist_new_uint(u64val)); + + u64val = _plist_dict_get_uint(parameters, "Baobab,ChipID"); + plist_dict_set_item(request, "Baobab,ChipID", plist_new_uint(u64val)); + + node = plist_dict_get_item(parameters, "Baobab,ECID"); + if (node) { + plist_dict_set_item(request, "Baobab,ECID", plist_copy(node)); + } + + u64val = _plist_dict_get_uint(parameters, "Baobab,Life"); + plist_dict_set_item(request, "Baobab,Life", plist_new_uint(u64val)); + + u64val = _plist_dict_get_uint(parameters, "Baobab,ManifestEpoch"); + plist_dict_set_item(request, "Baobab,ManifestEpoch", plist_new_uint(u64val)); + + isprod = _plist_dict_get_bool(parameters, "Baobab,ProductionMode"); + plist_dict_set_item(request, "Baobab,ProductionMode", plist_new_bool(isprod)); + + u64val = _plist_dict_get_uint(parameters, "Baobab,SecurityDomain"); + plist_dict_set_item(request, "Baobab,SecurityDomain", plist_new_uint(u64val)); + + node = plist_dict_get_item(parameters, "Baobab,UpdateNonce"); + if (node) { + plist_dict_set_item(request, "Baobab,UpdateNonce", plist_copy(node)); + } + + char *comp_name = NULL; + plist_dict_iter iter = NULL; + plist_dict_new_iter(manifest_node, &iter); + while (iter) { + node = NULL; + comp_name = NULL; + plist_dict_next_item(manifest_node, iter, &comp_name, &node); + if (comp_name == NULL) { + node = NULL; + break; + } + if (strncmp(comp_name, "Baobab,", 7) == 0) { + plist_t manifest_entry = plist_copy(node); + + plist_dict_remove_item(manifest_entry, "Info"); + plist_dict_set_item(manifest_entry, "EPRO", plist_new_bool(isprod)); + + /* finally add entry to request */ + plist_dict_set_item(request, comp_name, manifest_entry); + } + free(comp_name); + } + free(iter); + + /* apply overrides */ + if (overrides) { + plist_dict_merge(&request, overrides); + } + return 0; +} + static size_t tss_write_callback(char* data, size_t size, size_t nmemb, tss_response* response) { size_t total = size * nmemb; if (total != 0) { diff --git a/src/tss.h b/src/tss.h index 86dce42..3590aed 100644 --- a/src/tss.h +++ b/src/tss.h @@ -47,6 +47,7 @@ int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t ov int tss_request_add_vinyl_tags(plist_t request, plist_t parameters, plist_t overrides); int tss_request_add_rose_tags(plist_t request, plist_t parameters, plist_t overrides); int tss_request_add_veridian_tags(plist_t request, plist_t parameters, plist_t overrides); +int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overrides); int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters); int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters); -- cgit v1.1-32-gdbae