summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2022-04-06 14:21:53 +0200
committerGravatar Nikias Bassen2022-04-06 14:21:53 +0200
commit7eaa1fa8546bfa12d23ba30f81db54ae2ff64784 (patch)
tree8a18e029e5bf96e0034d596660041842e8535942
parente28d96d4e976ecb19a4d2a094609f122e08ea8fa (diff)
downloadidevicerestore-7eaa1fa8546bfa12d23ba30f81db54ae2ff64784.tar.gz
idevicerestore-7eaa1fa8546bfa12d23ba30f81db54ae2ff64784.tar.bz2
Add support for Timer,* components and TSS found in iPad Air 5th gen firmware
-rw-r--r--src/restore.c204
-rw-r--r--src/tss.c148
-rw-r--r--src/tss.h1
3 files changed, 353 insertions, 0 deletions
diff --git a/src/restore.c b/src/restore.c
index ef907ba..48eca78 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -2683,6 +2683,204 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct
return response;
}
+static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info)
+{
+ char comp_name[64];
+ char *comp_path = NULL;
+ plist_t comp_node = NULL;
+ unsigned char* component_data = NULL;
+ unsigned int component_size = 0;
+ ftab_t ftab = NULL;
+ ftab_t rftab = NULL;
+ uint32_t ftag = 0;
+ plist_t parameters = NULL;
+ plist_t request = NULL;
+ plist_t response = NULL;
+ plist_t node = NULL;
+ const char* ticket_name = NULL;
+ uint32_t tag = 0;
+ int ret;
+
+ /* create Timer request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create Timer TSS request\n");
+ return NULL;
+ }
+
+ parameters = plist_new_dict();
+
+ /* add manifest for current build_identity to parameters */
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
+ if (client->image4supported) {
+ plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1));
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(1));
+ } else {
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(0));
+ }
+
+ /* add Timer,* tags from info dictionary to parameters */
+ plist_t info_array = plist_dict_get_item(p_info, "InfoArray");
+ if (!info_array) {
+ error("ERROR: Could not find InfoArray in info dictionary\n");
+ plist_free(parameters);
+ return NULL;
+ } else {
+ plist_t info_dict = plist_array_get_item(info_array, 0);
+ plist_t hwid = plist_dict_get_item(info_dict, "HardwareID");
+ uint64_t u64val;
+ uint8_t bval;
+ tag = (uint32_t)_plist_dict_get_uint(info_dict, "TagNumber");
+ char key[64];
+
+ plist_dict_set_item(parameters, "TagNumber", plist_new_uint(tag));
+ plist_t node = plist_dict_get_item(info_dict, "TicketName");
+ if (node) {
+ ticket_name = plist_get_string_ptr(node, NULL);
+ plist_dict_set_item(parameters, "TicketName", plist_copy(node));
+ }
+
+ sprintf(key, "Timer,ChipID,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "ChipID");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,BoardID,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "BoardID");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,ECID,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "ECID");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ plist_t p_nonce = plist_dict_get_item(hwid, "Nonce");
+ if (p_nonce) {
+ sprintf(key, "Timer,Nonce,%u", tag);
+ plist_dict_set_item(parameters, key, plist_copy(p_nonce));
+ }
+
+ sprintf(key, "Timer,SecurityMode,%u", tag);
+ bval = _plist_dict_get_bool(hwid, "SecurityMode");
+ plist_dict_set_item(parameters, key, plist_new_bool(bval));
+
+ sprintf(key, "Timer,SecurityDomain,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "SecurityDomain");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,ProductionMode,%u", tag);
+ u64val = _plist_dict_get_uint(hwid, "ProductionStatus");
+ plist_dict_set_item(parameters, key, plist_new_uint(u64val));
+ }
+ plist_t ap_info = plist_dict_get_item(p_info, "APInfo");
+ if (!ap_info) {
+ error("ERROR: Could not find APInfo in info dictionary\n");
+ plist_free(parameters);
+ return NULL;
+ } else {
+ plist_dict_merge(parameters, ap_info);
+ }
+
+ /* add required tags for Timer TSS request */
+ tss_request_add_timer_tags(request, parameters, NULL);
+
+ plist_free(parameters);
+
+ info("Sending %s TSS request...\n", ticket_name);
+ response = tss_request_send(request, client->tss_url);
+ plist_free(request);
+ if (response == NULL) {
+ error("ERROR: Unable to fetch %s\n", ticket_name);
+ return NULL;
+ }
+
+ if (plist_dict_get_item(response, ticket_name)) {
+ info("Received %s\n", ticket_name);
+ } else {
+ error("ERROR: No '%s' in TSS response, this might not work\n", ticket_name);
+ }
+
+ sprintf(comp_name, "Timer,RTKitOS,%u", tag);
+ if (build_identity_has_component(build_identity, comp_name)) {
+ 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;
+ }
+ 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;
+ }
+ if (ftab_parse(component_data, component_size, &ftab, &ftag) != 0) {
+ free(component_data);
+ error("ERROR: Failed to parse '%s' component data.\n", comp_name);
+ return NULL;
+ }
+ free(component_data);
+ component_data = NULL;
+ component_size = 0;
+ if (ftag != 'rkos') {
+ error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');
+ }
+ } else {
+ info("NOTE: Build identity does not have a '%s' component.\n", comp_name);
+ }
+
+ sprintf(comp_name, "Timer,RestoreRTKitOS,%u", tag);
+ if (build_identity_has_component(build_identity, comp_name)) {
+ if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ ftab_free(ftab);
+ error("ERROR: Unable to get path for '%s' component\n", comp_name);
+ return NULL;
+ }
+ ret = extract_component(client->ipsw, comp_path, &component_data, &component_size);
+ free(comp_path);
+ comp_path = NULL;
+ if (ret < 0) {
+ ftab_free(ftab);
+ error("ERROR: Unable to extract '%s' component\n", comp_name);
+ return NULL;
+ }
+
+ ftag = 0;
+ if (ftab_parse(component_data, component_size, &rftab, &ftag) != 0) {
+ free(component_data);
+ ftab_free(ftab);
+ error("ERROR: Failed to parse '%s' component data.\n", comp_name);
+ return NULL;
+ }
+ free(component_data);
+ component_data = NULL;
+ component_size = 0;
+ if (ftag != 'rkos') {
+ error("WARNING: Unexpected tag 0x%08x, expected 0x%08x; continuing anyway.\n", ftag, 'rkos');
+ }
+
+ if (ftab_get_entry_ptr(rftab, 'rrko', &component_data, &component_size) == 0) {
+ ftab_add_entry(ftab, 'rrko', component_data, component_size);
+ } else {
+ error("ERROR: Could not find 'rrko' entry in ftab. This will probably break things.\n");
+ }
+ ftab_free(rftab);
+ component_data = NULL;
+ component_size = 0;
+ } else {
+ info("NOTE: Build identity does not have a '%s' component.\n", comp_name);
+ }
+
+ ftab_write(ftab, &component_data, &component_size);
+ ftab_free(ftab);
+
+ 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;
@@ -2776,6 +2974,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, "AppleTypeCRetimer") == 0) {
+ fwdict = restore_get_timer_firmware_data(restore, client, build_identity, p_info);
+ if (fwdict == NULL) {
+ error("ERROR: %s: Couldn't get AppleTypeCRetimer 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 084ad10..9c3ad05 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -490,6 +490,48 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity)
}
node = NULL;
+ /* add Timer,BoardID,1 */
+ node = plist_dict_get_item(build_identity, "Timer,BoardID,1");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,BoardID,1", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,BoardID,2 */
+ node = plist_dict_get_item(build_identity, "Timer,BoardID,2");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,BoardID,2", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,ChipID,1 */
+ node = plist_dict_get_item(build_identity, "Timer,ChipID,1");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,ChipID,1", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,ChipID,2 */
+ node = plist_dict_get_item(build_identity, "Timer,ChipID,2");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,ChipID,2", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,SecurityDomain,1 */
+ node = plist_dict_get_item(build_identity, "Timer,SecurityDomain,1");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,SecurityDomain,1", plist_copy(node));
+ }
+ node = NULL;
+
+ /* add Timer,SecurityDomain,2 */
+ node = plist_dict_get_item(build_identity, "Timer,SecurityDomain,2");
+ if (node) {
+ plist_dict_set_item(parameters, "Timer,SecurityDomain,2", 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) {
@@ -1810,6 +1852,112 @@ int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overr
return 0;
}
+int tss_request_add_timer_tags(plist_t request, plist_t parameters, plist_t overrides)
+{
+ plist_t node = NULL;
+ uint64_t u64val = 0;
+ uint8_t bval = 0;
+ uint32_t tag = 0;
+ char *ticket_name = 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 Timer ticket */
+ plist_dict_set_item(request, "@BBTicket", plist_new_bool(1));
+
+ node = plist_dict_get_item(parameters, "TicketName");
+ if (!node) {
+ error("ERROR: %s: Missing TicketName\n", __func__);
+ return -1;
+ }
+ char key[64];
+ sprintf(key, "@%s", plist_get_string_ptr(node, NULL));
+
+ plist_dict_set_item(request, key, plist_new_bool(1));
+
+ tag = (uint32_t)_plist_dict_get_uint(parameters, "TagNumber");
+
+ sprintf(key, "Timer,BoardID,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,ChipID,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,SecurityDomain,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,SecurityMode,%u", tag);
+ bval = _plist_dict_get_bool(parameters, key);
+ plist_dict_set_item(request, key, plist_new_bool(bval));
+
+ sprintf(key, "Timer,ProductionMode,%u", tag);
+ bval = _plist_dict_get_bool(parameters, key);
+ plist_dict_set_item(request, key, plist_new_bool(bval));
+
+ sprintf(key, "Timer,ECID,%u", tag);
+ u64val = _plist_dict_get_uint(parameters, key);
+ plist_dict_set_item(request, key, plist_new_uint(u64val));
+
+ sprintf(key, "Timer,Nonce,%u", tag);
+ plist_t p_nonce = plist_dict_get_item(parameters, key);
+ plist_dict_set_item(request, key, plist_copy(p_nonce));
+
+ 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, "Timer,", 6)) {
+ plist_t manifest_entry = plist_copy(node);
+
+ /* handle RestoreRequestRules */
+ plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules");
+ if (rules) {
+ debug("DEBUG: Applying restore request rules for entry %s\n", comp_name);
+ tss_entry_apply_restore_request_rules(manifest_entry, parameters, rules);
+ }
+
+ /* Make sure we have a Digest key for Trusted items even if empty */
+ plist_t node = plist_dict_get_item(manifest_entry, "Trusted");
+ if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
+ uint8_t trusted;
+ plist_get_bool_val(node, &trusted);
+ if (trusted && !plist_access_path(manifest_entry, 1, "Digest")) {
+ debug("DEBUG: No Digest data, using empty value for entry %s\n", comp_name);
+ plist_dict_set_item(manifest_entry, "Digest", plist_new_data(NULL, 0));
+ }
+ }
+
+ plist_dict_remove_item(manifest_entry, "Info");
+
+ /* 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 3590aed..8464f11 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -48,6 +48,7 @@ int tss_request_add_vinyl_tags(plist_t request, plist_t parameters, plist_t over
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_timer_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);