From 5d95b2ceabe9108a197db43224fb1a497239829a Mon Sep 17 00:00:00 2001 From: Rudolf Tammekivi Date: Wed, 16 Jan 2019 04:25:33 +0100 Subject: restore/tss: Add support for Yonkers firmware data and TSS request --- src/restore.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/tss.c | 90 +++++++++++++++++++++++++++++++++++ src/tss.h | 1 + 3 files changed, 237 insertions(+), 1 deletion(-) diff --git a/src/restore.c b/src/restore.c index 9248d7f..5e5bcec 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1973,6 +1973,146 @@ plist_t restore_get_savage_firmware_data(restored_client_t restore, struct idevi return response; } +plist_t restore_get_yonkers_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +{ + char *comp_name = NULL; + 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; + uint8_t isprod = 1; + uint64_t fabrevision = (uint64_t)-1; + int ret; + + node = plist_dict_get_item(p_info, "Yonkers,ProductionMode"); + if (node && (plist_get_node_type(node) == PLIST_BOOLEAN)) { + plist_get_bool_val(node, &isprod); + } + + node = plist_dict_get_item(p_info, "Yonkers,FabRevision"); + if (node && (plist_get_node_type(node) == PLIST_UINT)) { + plist_get_uint_val(node, &fabrevision); + } + + plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest"); + if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { + error("ERROR: Unable to find manifest node\n"); + return NULL; + } + plist_dict_iter iter = NULL; + plist_dict_new_iter(manifest_node, &iter); + while (1) { + plist_dict_next_item(manifest_node, iter, &comp_name, &node); + if (comp_name == NULL) { + node = NULL; + break; + } + if (strncmp(comp_name, "Yonkers,", 8) == 0) { + int target_node = 1; + plist_t sub_node; + if ((sub_node = plist_dict_get_item(node, "EPRO")) != NULL && plist_get_node_type(sub_node) == PLIST_BOOLEAN) { + uint8_t b = 0; + plist_get_bool_val(sub_node, &b); + target_node &= ((isprod) ? b : !b); + } + if ((sub_node = plist_dict_get_item(node, "FabRevision")) != NULL && plist_get_node_type(sub_node) == PLIST_UINT) { + uint64_t v = 0; + plist_get_uint_val(sub_node, &v); + target_node &= (v == fabrevision); + } + if (target_node) { + comp_node = node; + break; + } + } + free(comp_name); + comp_name = NULL; + } + free(iter); + node = NULL; + + if (comp_name == NULL) { + error("ERROR: No Yonkers node for %s/%lu\n", (isprod) ? "Production" : "Development", (unsigned long)fabrevision); + return NULL; + } + debug("DEBUG: %s: using %s\n", __func__, comp_name); + + if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + error("ERROR: Unable get path for '%s' component\n", comp_name); + free(comp_name); + return NULL; + } + + 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); + free(comp_name); + return NULL; + } + + /* create Yonkers request */ + request = tss_request_new(NULL); + if (request == NULL) { + error("ERROR: Unable to create Yonkers TSS request\n"); + free(component_data); + free(comp_name); + return NULL; + } + + parameters = plist_new_dict(); + + /* add manifest for current build_identity to parameters */ + tss_parameters_add_from_manifest(parameters, build_identity); + + /* add Yonkers,* tags from info dictionary to parameters */ + plist_dict_merge(¶meters, p_info); + + /* add required tags for Yonkers TSS request */ + tss_request_add_yonkers_tags(request, parameters, NULL); + + plist_free(parameters); + + if (comp_node != NULL) { + plist_t comp_dict = plist_copy(comp_node); + plist_dict_remove_item(comp_dict, "Info"); + plist_dict_set_item(request, comp_name, comp_dict); + } + + free(comp_name); + comp_name = NULL; + + info("Sending Yonkers TSS request...\n"); + response = tss_request_send(request, client->tss_url); + plist_free(request); + if (response == NULL) { + error("ERROR: Unable to fetch Yonkers ticket\n"); + free(component_data); + return NULL; + } + + if (plist_dict_get_item(response, "Yonkers,Ticket")) { + info("Received Yonkers ticket\n"); + } else { + error("ERROR: No 'Yonkers,Ticket' in TSS response, this might not work\n"); + } + + plist_t firmware_data = plist_new_dict(); + plist_dict_set_item(firmware_data, "YonkersFirmware", plist_new_data((char *)component_data, (uint64_t)component_size)); + plist_dict_set_item(response, "FirmwareData", firmware_data); + + free(component_data); + component_data = NULL; + component_size = 0; + + return response; +} + 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; @@ -2036,7 +2176,12 @@ int restore_send_firmware_updater_data(restored_client_t restore, struct idevice goto error_out; } } else if (strcmp(s_updater_name, "Savage") == 0) { - fwdict = restore_get_savage_firmware_data(restore, client, build_identity, p_info); + plist_t p_info2 = plist_dict_get_item(p_info, "YonkersDeviceInfo"); + if (p_info2 && plist_get_node_type(p_info2) == PLIST_DICT) { + fwdict = restore_get_yonkers_firmware_data(restore, client, build_identity, p_info2); + } else { + fwdict = restore_get_savage_firmware_data(restore, client, build_identity, p_info); + } if (fwdict == NULL) { error("ERROR: %s: Couldn't get Savage firmware data\n", __func__); goto error_out; diff --git a/src/tss.c b/src/tss.c index 6340382..dd3cf37 100644 --- a/src/tss.c +++ b/src/tss.c @@ -247,6 +247,51 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) } node = NULL; + /* Yonkers,BoardID - Used for Yonkers firmware request */ + node = plist_dict_get_item(build_identity, "Yonkers,BoardID"); + if (node) { + if (plist_get_node_type(node) == PLIST_STRING) { + char *strval = NULL; + int intval = 0; + plist_get_string_val(node, &strval); + sscanf(strval, "%x", &intval); + plist_dict_set_item(parameters, "Yonkers,BoardID", plist_new_uint(intval)); + } else { + plist_dict_set_item(parameters, "Yonkers,BoardID", plist_copy(node)); + } + } + node = NULL; + + /* Yonkers,ChipID - Used for Yonkers firmware request */ + node = plist_dict_get_item(build_identity, "Yonkers,ChipID"); + if (node) { + if (plist_get_node_type(node) == PLIST_STRING) { + char *strval = NULL; + int intval = 0; + plist_get_string_val(node, &strval); + sscanf(strval, "%x", &intval); + plist_dict_set_item(parameters, "Yonkers,ChipID", plist_new_uint(intval)); + } else { + plist_dict_set_item(parameters, "Yonkers,ChipID", plist_copy(node)); + } + } + node = NULL; + + /* add Yonkers,PatchEpoch - Used for Yonkers firmware request */ + node = plist_dict_get_item(build_identity, "Yonkers,PatchEpoch"); + if (node) { + if (plist_get_node_type(node) == PLIST_STRING) { + char *strval = NULL; + int intval = 0; + plist_get_string_val(node, &strval); + sscanf(strval, "%x", &intval); + plist_dict_set_item(parameters, "Yonkers,PatchEpoch", plist_new_uint(intval)); + } else { + plist_dict_set_item(parameters, "Yonkers,PatchEpoch", plist_copy(node)); + } + } + node = NULL; + /* add build identity manifest dictionary */ node = plist_dict_get_item(build_identity, "Manifest"); if (!node || plist_get_node_type(node) != PLIST_DICT) { @@ -908,6 +953,51 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove return 0; } +int tss_request_add_yonkers_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 Savage,Ticket */ + plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); + plist_dict_set_item(request, "@Yonkers,Ticket", plist_new_bool(1)); + + /* add SEP */ + node = plist_access_path(manifest_node, 2, "SEP", "Digest"); + if (!node) { + error("ERROR: Unable to get SEP digest from manifest\n"); + return -1; + } + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "Digest", plist_copy(node)); + plist_dict_set_item(request, "SEP", dict); + + { + static const char *keys[] = {"Yonkers,AllowOfflineBoot", "Yonkers,BoardID", "Yonkers,ChipID", "Yonkers,ECID", "Yonkers,Nonce", "Yonkers,PatchEpoch", "Yonkers,ProductionMode", "Yonkers,ReadECKey", "Yonkers,ReadFWKey", }; + int i; + for (i = 0; i < (int)(sizeof(keys) / sizeof(keys[0])); ++i) { + node = plist_dict_get_item(parameters, keys[i]); + if (!node) { + error("ERROR: %s: Unable to find required %s in parameters\n", __func__, keys[i]); + } + plist_dict_set_item(request, keys[i], plist_copy(node)); + node = NULL; + } + } + + /* 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 0c62d26..465e9dc 100644 --- a/src/tss.h +++ b/src/tss.h @@ -41,6 +41,7 @@ int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrid int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t overrides); int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrides); int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t overrides); +int tss_request_add_yonkers_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