diff options
author | 2024-10-15 22:09:43 +0200 | |
---|---|---|
committer | 2024-10-15 22:09:43 +0200 | |
commit | 151c680feb6a0775d1b979dbdfca2ac6fdfc8cad (patch) | |
tree | 5ced724a09715e506df91a51fb8a9b7f69b9b057 /src | |
parent | f4a18ee13dd84d76dd6ebb9b21cd6bce6f37e4ec (diff) | |
download | idevicerestore-151c680feb6a0775d1b979dbdfca2ac6fdfc8cad.tar.gz idevicerestore-151c680feb6a0775d1b979dbdfca2ac6fdfc8cad.tar.bz2 |
Fix iPhone 16 restore from normal mode and add support for RecoveryOS
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 3 | ||||
-rw-r--r-- | src/dfu.c | 2 | ||||
-rw-r--r-- | src/idevicerestore.c | 60 | ||||
-rw-r--r-- | src/idevicerestore.h | 2 | ||||
-rw-r--r-- | src/img4.c | 193 | ||||
-rw-r--r-- | src/img4.h | 2 | ||||
-rw-r--r-- | src/normal.c | 26 | ||||
-rw-r--r-- | src/normal.h | 1 | ||||
-rw-r--r-- | src/recovery.c | 2 | ||||
-rw-r--r-- | src/restore.c | 391 |
10 files changed, 578 insertions, 104 deletions
diff --git a/src/common.h b/src/common.h index 8085a1a..872d2f9 100644 --- a/src/common.h +++ b/src/common.h @@ -104,7 +104,9 @@ struct idevicerestore_client_t { int nonce_size; int image4supported; plist_t build_manifest; + plist_t firmware_preflight_info; plist_t preflight_info; + plist_t parameters; char* udid; char* srnm; ipsw_archive_t ipsw; @@ -131,6 +133,7 @@ struct idevicerestore_client_t { cond_t device_event_cond; int ignore_device_add_events; plist_t macos_variant; + plist_t recovery_variant; char* restore_variant; char* filesystem; int delete_fs; @@ -168,7 +168,7 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide unsigned char* data = NULL; uint32_t size = 0; - if (personalize_component(component, component_data, component_size, tss, &data, &size) < 0) { + if (personalize_component(client, component, component_data, component_size, tss, &data, &size) < 0) { error("ERROR: Unable to get personalized component: %s\n", component); free(component_data); return -1; diff --git a/src/idevicerestore.c b/src/idevicerestore.c index fb0b329..b8bb1d0 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -1227,6 +1227,29 @@ int idevicerestore_start(struct idevicerestore_client_t* client) } else { free(nonce); } + if (client->mode == MODE_NORMAL) { + plist_t ap_params = normal_get_lockdown_value(client, NULL, "ApParameters"); + if (ap_params) { + if (!client->parameters) { + client->parameters = plist_new_dict(); + } + plist_dict_merge(&client->parameters, ap_params); + plist_t p_sep_nonce = plist_dict_get_item(ap_params, "SepNonce"); + uint64_t sep_nonce_size = 0; + const char* sep_nonce = plist_get_data_ptr(p_sep_nonce, &sep_nonce_size); + info("Getting SepNonce in normal mode... "); + int i = 0; + for (i = 0; i < sep_nonce_size; i++) { + info("%02x ", (unsigned char)sep_nonce[i]); + } + info("\n"); + plist_free(ap_params); + } + plist_t req_nonce_slot = plist_access_path(build_identity, 2, "Info", "RequiresNonceSlot"); + if (req_nonce_slot) { + plist_dict_set_item(client->parameters, "RequiresNonceSlot", plist_copy(req_nonce_slot)); + } + } } if (client->flags & FLAG_QUIT) { @@ -1263,8 +1286,12 @@ int idevicerestore_start(struct idevicerestore_client_t* client) plist_t recovery_variant = plist_access_path(build_identity, 2, "Info", "RecoveryVariant"); if (recovery_variant) { const char* recovery_variant_str = plist_get_string_ptr(recovery_variant, NULL); - plist_t recovery_build_identity = build_manifest_get_build_identity_for_model_with_variant(client->build_manifest, client->device->hardware_model, recovery_variant_str, 1); - if (get_tss_response(client, recovery_build_identity, &client->tss_recoveryos_root_ticket) < 0) { + client->recovery_variant = build_manifest_get_build_identity_for_model_with_variant(client->build_manifest, client->device->hardware_model, recovery_variant_str, 1); + if (!client->recovery_variant) { + error("ERROR: Variant '%s' not found in BuildManifest\n", recovery_variant_str); + return -1; + } + if (get_tss_response(client, client->recovery_variant, &client->tss_recoveryos_root_ticket) < 0) { error("ERROR: Unable to get SHSH blobs for this device (%s)\n", recovery_variant_str); return -1; } @@ -1614,6 +1641,9 @@ void idevicerestore_client_free(struct idevicerestore_client_t* client) if (client->build_manifest) { plist_free(client->build_manifest); } + if (client->firmware_preflight_info) { + plist_free(client->firmware_preflight_info); + } if (client->preflight_info) { plist_free(client->preflight_info); } @@ -2276,17 +2306,21 @@ int get_tss_response(struct idevicerestore_client_t* client, plist_t build_ident /* populate parameters */ plist_t parameters = plist_new_dict(); + plist_dict_merge(¶meters, client->parameters); + plist_dict_set_item(parameters, "ApECID", plist_new_uint(client->ecid)); if (client->nonce) { plist_dict_set_item(parameters, "ApNonce", plist_new_data((const char*)client->nonce, client->nonce_size)); } - unsigned char* sep_nonce = NULL; - unsigned int sep_nonce_size = 0; - get_sep_nonce(client, &sep_nonce, &sep_nonce_size); - if (sep_nonce) { - plist_dict_set_item(parameters, "ApSepNonce", plist_new_data((const char*)sep_nonce, sep_nonce_size)); - free(sep_nonce); + if (!plist_dict_get_item(parameters, "SepNonce")) { + unsigned char* sep_nonce = NULL; + unsigned int sep_nonce_size = 0; + get_sep_nonce(client, &sep_nonce, &sep_nonce_size); + if (sep_nonce) { + plist_dict_set_item(parameters, "ApSepNonce", plist_new_data((const char*)sep_nonce, sep_nonce_size)); + free(sep_nonce); + } } plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1)); @@ -2344,7 +2378,7 @@ int get_tss_response(struct idevicerestore_client_t* client, plist_t build_ident if (client->mode == MODE_NORMAL) { /* normal mode; request baseband ticket aswell */ plist_t pinfo = NULL; - normal_get_preflight_info(client, &pinfo); + normal_get_firmware_preflight_info(client, &pinfo); if (pinfo) { plist_dict_copy_data(parameters, pinfo, "BbNonce", "Nonce"); plist_dict_copy_uint(parameters, pinfo, "BbChipID", "ChipID"); @@ -2365,6 +2399,10 @@ int get_tss_response(struct idevicerestore_client_t* client, plist_t build_ident tss_request_add_vinyl_tags(request, parameters, NULL); } } + client->firmware_preflight_info = pinfo; + pinfo = NULL; + + normal_get_preflight_info(client, &pinfo); client->preflight_info = pinfo; } @@ -2718,7 +2756,7 @@ int extract_component(ipsw_archive_t ipsw, const char* path, unsigned char** com return 0; } -int personalize_component(const char *component_name, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** personalized_component, unsigned int* personalized_component_size) +int personalize_component(struct idevicerestore_client_t* client, const char *component_name, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** personalized_component, unsigned int* personalized_component_size) { unsigned char* component_blob = NULL; unsigned int component_blob_size = 0; @@ -2727,7 +2765,7 @@ int personalize_component(const char *component_name, const unsigned char* compo if (tss_response && plist_dict_get_item(tss_response, "ApImg4Ticket")) { /* stitch ApImg4Ticket into IMG4 file */ - img4_stitch_component(component_name, component_data, component_size, tss_response, &stitched_component, &stitched_component_size); + img4_stitch_component(component_name, component_data, component_size, client->parameters, tss_response, &stitched_component, &stitched_component_size); } else { /* try to get blob for current component from tss response */ if (tss_response && tss_response_get_blob_by_entry(tss_response, component_name, &component_blob) < 0) { diff --git a/src/idevicerestore.h b/src/idevicerestore.h index 5afcf1a..fe9d11f 100644 --- a/src/idevicerestore.h +++ b/src/idevicerestore.h @@ -115,7 +115,7 @@ int build_identity_has_component(plist_t build_identity, const char* component); int build_identity_get_component_path(plist_t build_identity, const char* component, char** path); int ipsw_extract_filesystem(ipsw_archive_t ipsw, plist_t build_identity, char** filesystem); int extract_component(ipsw_archive_t ipsw, const char* path, unsigned char** component_data, unsigned int* component_size); -int personalize_component(const char *component, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** personalized_component, unsigned int* personalized_component_size); +int personalize_component(struct idevicerestore_client_t* client, const char *component, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** personalized_component, unsigned int* personalized_component_size); int get_preboard_manifest(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* manifest); const char* get_component_name(const char* filename); @@ -26,6 +26,7 @@ #include "common.h" #include "img4.h" +#include "endianness.h" #define ASN1_PRIVATE 0xc0 #define ASN1_PRIMITIVE_TAG 0x1f @@ -395,7 +396,7 @@ static const char *_img4_get_component_tag(const char *compname) return NULL; } -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) +int img4_stitch_component(const char* component_name, const unsigned char* component_data, unsigned int component_size, plist_t parameters, plist_t tss_response, unsigned char** img4_data, unsigned int *img4_size) { unsigned char* magic_header = NULL; unsigned int magic_header_size = 0; @@ -459,14 +460,17 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo snprintf(tbm_key, strlen(component_name)+5, "%s-TBM", component_name); plist_t tbm_dict = plist_dict_get_item(tss_response, tbm_key); free(tbm_key); + uint64_t ucon_size = 0; + const char* ucon_data = NULL; + uint64_t ucer_size = 0; + const char* ucer_data = NULL; if (tbm_dict) { plist_t dt = plist_dict_get_item(tbm_dict, "ucon"); if (!dt) { error("ERROR: %s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name); return -1; } - uint64_t ucon_size = 0; - const char* ucon_data = plist_get_data_ptr(dt, &ucon_size); + ucon_data = plist_get_data_ptr(dt, &ucon_size); if (!ucon_data) { error("ERROR: %s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name); return -1; @@ -476,76 +480,141 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo error("ERROR: %s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name); return -1; } - uint64_t ucer_size = 0; - const char* ucer_data = plist_get_data_ptr(dt, &ucer_size); + ucer_data = plist_get_data_ptr(dt, &ucer_size); if (!ucer_data) { error("ERROR: %s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name); return -1; } + } + + int nonce_slot_required = plist_dict_get_bool(parameters, "RequiresNonceSlot") && (!strcmp(component_name, "SEP") || !strcmp(component_name, "SepStage1") || !strcmp(component_name, "LLB")); - unsigned char *im4rset = (unsigned char*)malloc(16 + 8 + 8 + ucon_size + 16 + 8 + 8 + ucer_size + 16); + if (ucon_data || ucer_data || nonce_slot_required) { + size_t im4r_size = 16; + if (ucon_data) { + im4r_size += 8 + 8 + ucon_size + 16; + } + if (ucer_data) { + im4r_size += 8 + 8 + ucer_size + 16; + } + if (nonce_slot_required) { + im4r_size += 16; + } + unsigned char *im4rset = (unsigned char*)malloc(im4r_size); unsigned char *p_im4rset = im4rset; unsigned int im4rlen = 0; + // ----------- anid/snid ------- + if (nonce_slot_required) { + const char* tag_name = NULL; + uint64_t tag_value = 0; + if (!strcmp(component_name, "SEP") || !strcmp(component_name, "SepStage1")) { + tag_name = "snid"; + tag_value = 2; + if (plist_dict_get_item(parameters, "SepNonceSlotID")) { + tag_value = plist_dict_get_uint(parameters, "SepNonceSlotID"); + } + } else { + tag_name = "anid"; + tag_value = 0; + if (plist_dict_get_item(parameters, "ApNonceSlotID")) { + tag_value = plist_dict_get_uint(parameters, "ApNonceSlotID"); + } + } + // write priv anid/snid element + asn1_write_priv_element(&p_im4rset, &im4rlen, __bswap_32(*(uint32_t*)tag_name)); + // write anid/snid IA5STRING and anid/snid value + unsigned char inner_seq[16]; + unsigned char *p_inner_seq = &inner_seq[0]; + unsigned int inner_seq_hdr_len = 0; + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_IA5_STRING, (void*)tag_name, -1); + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_INTEGER, (void*)&tag_value, -1); + + // write anid/snid sequence + unsigned char elem_seq[8]; + unsigned char *p = &elem_seq[0]; + unsigned int seq_hdr_len = 0; + asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, inner_seq_hdr_len, &p, &seq_hdr_len); + + // add size to priv anid/snid element + asn1_write_size(inner_seq_hdr_len + seq_hdr_len, &p_im4rset, &im4rlen); + + // put it together + memcpy(p_im4rset, elem_seq, seq_hdr_len); + p_im4rset += seq_hdr_len; + im4rlen += seq_hdr_len; + memcpy(p_im4rset, inner_seq, inner_seq_hdr_len); + p_im4rset += inner_seq_hdr_len; + im4rlen += inner_seq_hdr_len; + } + // ----------- ucon ------------ - // write priv ucon element - asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"nocu"); - - // write ucon IA5STRING and ucon data - unsigned char ucon_seq[16]; - unsigned char *p_ucon_seq = &ucon_seq[0]; - unsigned int ucon_seq_hdr_len = 0; - asn1_write_element(&p_ucon_seq, &ucon_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucon", -1); - asn1_write_element_header(ASN1_OCTET_STRING, ucon_size, &p_ucon_seq, &ucon_seq_hdr_len); - - // write ucon sequence - unsigned char elem_seq[8]; - unsigned char *p = &elem_seq[0]; - unsigned int seq_hdr_len = 0; - asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, ucon_seq_hdr_len + ucon_size, &p, &seq_hdr_len); - - // add size to priv ucon element - asn1_write_size(ucon_seq_hdr_len + ucon_size + seq_hdr_len, &p_im4rset, &im4rlen); - - // put it together - memcpy(p_im4rset, elem_seq, seq_hdr_len); - p_im4rset += seq_hdr_len; - im4rlen += seq_hdr_len; - memcpy(p_im4rset, ucon_seq, ucon_seq_hdr_len); - p_im4rset += ucon_seq_hdr_len; - im4rlen += ucon_seq_hdr_len; - memcpy(p_im4rset, ucon_data, ucon_size); - p_im4rset += ucon_size; - im4rlen += ucon_size; + if (ucon_data) { + // write priv ucon element + asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"nocu"); + + // write ucon IA5STRING and ucon data header + unsigned char inner_seq[16]; + unsigned char *p_inner_seq = &inner_seq[0]; + unsigned int inner_seq_hdr_len = 0; + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucon", -1); + asn1_write_element_header(ASN1_OCTET_STRING, ucon_size, &p_inner_seq, &inner_seq_hdr_len); + + // write ucon sequence + unsigned char elem_seq[8]; + unsigned char *p = &elem_seq[0]; + unsigned int seq_hdr_len = 0; + asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, inner_seq_hdr_len + ucon_size, &p, &seq_hdr_len); + + // add size to priv ucon element + asn1_write_size(inner_seq_hdr_len + ucon_size + seq_hdr_len, &p_im4rset, &im4rlen); + + // put it together + memcpy(p_im4rset, elem_seq, seq_hdr_len); + p_im4rset += seq_hdr_len; + im4rlen += seq_hdr_len; + memcpy(p_im4rset, inner_seq, inner_seq_hdr_len); + p_im4rset += inner_seq_hdr_len; + im4rlen += inner_seq_hdr_len; + // write ucon data + memcpy(p_im4rset, ucon_data, ucon_size); + p_im4rset += ucon_size; + im4rlen += ucon_size; + } // ----------- ucer ------------ - // write priv ucer element - asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"recu"); - - // write ucon IA5STRING and ucer data - unsigned char ucer_seq[16]; - unsigned char *p_ucer_seq = &ucer_seq[0]; - unsigned int ucer_seq_hdr_len = 0; - asn1_write_element(&p_ucer_seq, &ucer_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucer", -1); - asn1_write_element_header(ASN1_OCTET_STRING, ucer_size, &p_ucer_seq, &ucer_seq_hdr_len); - - p = &elem_seq[0]; - seq_hdr_len = 0; - asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, ucer_seq_hdr_len + ucer_size, &p, &seq_hdr_len); - - // add size to priv ucer element - asn1_write_size(ucer_seq_hdr_len + ucer_size + seq_hdr_len, &p_im4rset, &im4rlen); - - // put it together - memcpy(p_im4rset, elem_seq, seq_hdr_len); - p_im4rset += seq_hdr_len; - im4rlen += seq_hdr_len; - memcpy(p_im4rset, ucer_seq, ucer_seq_hdr_len); - p_im4rset += ucer_seq_hdr_len; - im4rlen += ucer_seq_hdr_len; - memcpy(p_im4rset, ucer_data, ucer_size); - p_im4rset += ucer_size; - im4rlen += ucer_size; + if (ucer_data) { + // write priv ucer element + asn1_write_priv_element(&p_im4rset, &im4rlen, *(uint32_t*)"recu"); + + // write ucer IA5STRING and ucer data header + unsigned char inner_seq[16]; + unsigned char *p_inner_seq = &inner_seq[0]; + unsigned int inner_seq_hdr_len = 0; + asn1_write_element(&p_inner_seq, &inner_seq_hdr_len, ASN1_IA5_STRING, (void*)"ucer", -1); + asn1_write_element_header(ASN1_OCTET_STRING, ucer_size, &p_inner_seq, &inner_seq_hdr_len); + + // write ucer sequence + unsigned char elem_seq[8]; + unsigned char *p = &elem_seq[0]; + unsigned int seq_hdr_len = 0; + asn1_write_element_header(ASN1_SEQUENCE | ASN1_CONSTRUCTED, inner_seq_hdr_len + ucer_size, &p, &seq_hdr_len); + + // add size to priv ucer element + asn1_write_size(inner_seq_hdr_len + ucer_size + seq_hdr_len, &p_im4rset, &im4rlen); + + // put it together + memcpy(p_im4rset, elem_seq, seq_hdr_len); + p_im4rset += seq_hdr_len; + im4rlen += seq_hdr_len; + memcpy(p_im4rset, inner_seq, inner_seq_hdr_len); + p_im4rset += inner_seq_hdr_len; + im4rlen += inner_seq_hdr_len; + // write ucer data + memcpy(p_im4rset, ucer_data, ucer_size); + p_im4rset += ucer_size; + im4rlen += ucer_size; + } // now construct IM4R @@ -26,7 +26,7 @@ extern "C" { #endif -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); +int img4_stitch_component(const char* component_name, const unsigned char* component_data, unsigned int component_size, plist_t parameters, plist_t tss_response, unsigned char** img4_data, unsigned int *img4_size); int img4_create_local_manifest(plist_t request, plist_t build_identity, plist_t* manifest); #ifdef __cplusplus diff --git a/src/normal.c b/src/normal.c index e699bbe..9e46080 100644 --- a/src/normal.c +++ b/src/normal.c @@ -342,6 +342,18 @@ static int normal_get_nonce_by_key(struct idevicerestore_client_t* client, const int normal_get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, unsigned int* nonce_size) { + plist_t node = normal_get_lockdown_value(client, NULL, "ApParameters"); + if (PLIST_IS_DICT(node)) { + plist_t nonce_node = plist_dict_get_item(node, "SepNonce"); + if (nonce_node) { + uint64_t n_size = 0; + plist_get_data_val(nonce_node, (char**)nonce, &n_size); + *nonce_size = (unsigned int)n_size; + plist_free(node); + return 0; + } + } + plist_free(node); return normal_get_nonce_by_key(client, "SEPNonce", nonce, nonce_size); } @@ -365,7 +377,7 @@ int normal_is_image4_supported(struct idevicerestore_client_t* client) return bval; } -int normal_get_preflight_info(struct idevicerestore_client_t* client, plist_t *preflight_info) +int normal_get_firmware_preflight_info(struct idevicerestore_client_t* client, plist_t *preflight_info) { uint8_t has_telephony_capability = 0; plist_t node; @@ -389,6 +401,18 @@ int normal_get_preflight_info(struct idevicerestore_client_t* client, plist_t *p return 0; } +int normal_get_preflight_info(struct idevicerestore_client_t* client, plist_t *preflight_info) +{ + plist_t node = normal_get_lockdown_value(client, NULL, "PreflightInfo"); + if (PLIST_IS_DICT(node)) { + *preflight_info = node; + } else { + debug("DEBUG: No PreflightInfo available.\n"); + *preflight_info = NULL; + } + return 0; +} + int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_t manifest) { int result = -1; diff --git a/src/normal.h b/src/normal.h index 7741ac5..d3d7b0c 100644 --- a/src/normal.h +++ b/src/normal.h @@ -38,6 +38,7 @@ int normal_enter_recovery(struct idevicerestore_client_t* client); int normal_is_image4_supported(struct idevicerestore_client_t* client); int normal_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, unsigned int* nonce_size); int normal_get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, unsigned int* nonce_size); +int normal_get_firmware_preflight_info(struct idevicerestore_client_t* client, plist_t *preflight_info); int normal_get_preflight_info(struct idevicerestore_client_t* client, plist_t *preflight_info); plist_t normal_get_lockdown_value(struct idevicerestore_client_t* client, const char* domain, const char* key); int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_t manifest); diff --git a/src/recovery.c b/src/recovery.c index afda4a9..c451350 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -305,7 +305,7 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil return -1; } - ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size); free(component_data); if (ret < 0) { error("ERROR: Unable to get personalized component: %s\n", component); diff --git a/src/restore.c b/src/restore.c index 6fdf755..2daeea2 100644 --- a/src/restore.c +++ b/src/restore.c @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <libgen.h> +#include <math.h> #include <libimobiledevice/restore.h> #include <libimobiledevice/property_list_service.h> #include <libimobiledevice-glue/thread.h> @@ -1490,7 +1491,7 @@ int restore_send_component(struct idevicerestore_client_t* client, plist_t messa return -1; } - ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size); free(component_data); component_data = NULL; if (ret < 0) { @@ -1662,7 +1663,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message) return -1; } - ret = personalize_component(component, component_data, component_size, client->tss, &llb_data, &llb_size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &llb_data, &llb_size); free(component_data); component_data = NULL; component_size = 0; @@ -1718,7 +1719,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message) return -1; } - if (personalize_component(component, component_data, component_size, client->tss, &nor_data, &nor_size) < 0) { + if (personalize_component(client, component, component_data, component_size, client->tss, &nor_data, &nor_size) < 0) { free(iter); free(comp); free(comppath); @@ -1765,7 +1766,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message) return -1; } - ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &personalized_data, &personalized_size); free(component_data); component_data = NULL; component_size = 0; @@ -1790,7 +1791,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message) return -1; } - ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &personalized_data, &personalized_size); free(component_data); component_data = NULL; component_size = 0; @@ -1815,7 +1816,7 @@ int restore_send_nor(struct idevicerestore_client_t* client, plist_t message) return -1; } - ret = personalize_component(component, component_data, component_size, client->tss, &personalized_data, &personalized_size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &personalized_data, &personalized_size); free(component_data); component_data = NULL; component_size = 0; @@ -2518,7 +2519,7 @@ static int restore_send_image_data(struct idevicerestore_client_t *client, plist error("ERROR: Unable to extract component: %s\n", component); } - ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size); free(component_data); component_data = NULL; if (ret < 0) { @@ -4273,7 +4274,7 @@ int restore_send_personalized_boot_object_v3(struct idevicerestore_client_t* cli } // Personalize IMG4 - ret = personalize_component(component, component_data, component_size, client->tss, &data, &size); + ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size); free(component_data); component_data = NULL; if (ret < 0) { @@ -4439,7 +4440,7 @@ int restore_send_restore_local_policy(struct idevicerestore_client_t* client, pl return -1; } - ret = personalize_component(component, component_data, component_size, client->tss_localpolicy, &data, &size); + ret = personalize_component(client, component, component_data, component_size, client->tss_localpolicy, &data, &size); free(component_data); component_data = NULL; if (ret < 0) { @@ -4508,6 +4509,232 @@ int restore_send_buildidentity(struct idevicerestore_client_t* client, plist_t m return 0; } +int restore_send_recovery_os_file_asset_image(struct idevicerestore_client_t* client, plist_t message) +{ + char *fw_override_key = NULL; + plist_t node = plist_access_path(message, 2, "Arguments", "FWOverrideKey"); + if (PLIST_IS_STRING(node)) { + plist_get_string_val(node, &fw_override_key); + } + if (!fw_override_key) { + error("ERROR: Failed to get FWOverrideKey from arguments. Trying to continue anyway.\n"); + return -1; + } + + plist_t dict = plist_new_dict(); + if (!client->recovery_variant) { + error("ERROR: no RecoveryOS variant in BuildManifest. Trying to continue anyway.\n"); + plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); + restored_send(client->restore->client, dict); + plist_free(dict); + return 0; + } + + if (strncmp(fw_override_key, "RecoveryOS", 10) != 0) { + error("ERROR: FWOVerrideKey has unexpected prefix\n"); + plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); + restored_send(client->restore->client, dict); + plist_free(dict); + return 0; + } + + const char* component = fw_override_key+10; + char* path = NULL; + if (build_identity_get_component_path(client->recovery_variant, component, &path) < 0) { + error("ERROR: Unable to find %s path from recovery build identity. Trying to continue anyway.\n", component); + plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); + restored_send(client->restore->client, dict); + plist_free(dict); + return 0; + } + + unsigned char* component_data = NULL; + unsigned int component_size = 0; + int ret = extract_component(client->ipsw, path, &component_data, &component_size); + free(path); + path = NULL; + if (ret < 0) { + error("ERROR: Unable to extract component %s. Trying to continue anyway.\n", component); + plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); + restored_send(client->restore->client, dict); + plist_free(dict); + return 0; + } + + unsigned char* data = NULL; + unsigned int size = 0; + ret = personalize_component(client, component, component_data, component_size, client->tss_recoveryos_root_ticket, &data, &size); + free(component_data); + component_data = NULL; + if (ret < 0) { + error("ERROR: Unable to get personalized component %s. Trying to continue anyway.\n", component); + plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); + restored_send(client->restore->client, dict); + plist_free(dict); + return 0; + } + + info("Sending %s\n", fw_override_key); + + plist_dict_set_item(dict, "AdditionalBootImages", plist_new_data((char*)data, size)); + free(data); + restored_send(client->restore->client, dict); + plist_free(dict); + + return 0; +} + +int restore_send_recovery_os_iboot_fw_files_images(struct idevicerestore_client_t* client, plist_t message) +{ + plist_t build_id_manifest = plist_dict_get_item(client->recovery_variant, "Manifest"); + if (!build_id_manifest) { + error("ERROR: Missing Manifest dictionary in build identity?!\n"); + return -1; + } + + plist_t firmware_files = plist_new_dict(); + + plist_dict_iter iter = NULL; + plist_dict_new_iter(build_id_manifest, &iter); + if (iter) { + char *component = NULL; + plist_t manifest_entry; + do { + component = NULL; + manifest_entry = NULL; + plist_dict_next_item(build_id_manifest, iter, &component, &manifest_entry); + if (component && PLIST_IS_DICT(manifest_entry)) { + uint8_t loaded_by_iboot = 0; + uint8_t loaded_by_iboot_stage1 = 0; + plist_t fw_node; + + fw_node = plist_access_path(manifest_entry, 2, "Info", "IsLoadedByiBoot"); + if (fw_node && plist_get_node_type(fw_node) == PLIST_BOOLEAN) { + plist_get_bool_val(fw_node, &loaded_by_iboot); + } + fw_node = plist_access_path(manifest_entry, 2, "Info", "IsLoadedByiBootStage1"); + if (fw_node && plist_get_node_type(fw_node) == PLIST_BOOLEAN) { + plist_get_bool_val(fw_node, &loaded_by_iboot_stage1); + } + if (loaded_by_iboot || loaded_by_iboot_stage1) { + plist_t comp_path = plist_access_path(manifest_entry, 2, "Info", "Path"); + if (comp_path) { + const char* path = plist_get_string_ptr(comp_path, NULL); + unsigned char* component_data = NULL; + unsigned int component_size = 0; + int ret = extract_component(client->ipsw, path, &component_data, &component_size); + if (ret == 0) { + unsigned char* data = NULL; + unsigned int size = 0; + ret = personalize_component(client, component, component_data, component_size, client->tss_recoveryos_root_ticket, &data, &size); + free(component_data); + component_data = NULL; + if (ret == 0) { + plist_dict_set_item(firmware_files, component, plist_new_data((char*)data, size)); + free(data); + } + } + } + } + } + free(component); + } while (manifest_entry); + plist_mem_free(iter); + } + + plist_t dict = plist_new_dict(); + + if (plist_dict_get_size(firmware_files) == 0) { + plist_free(firmware_files); + info("NOTE: No iBoot firmware files. Continuing.\n"); + plist_dict_set_item(dict, "RecoveryOSNoAssetFound", plist_new_bool(1)); + restored_send(client->restore->client, dict); + plist_free(dict); + return 0; + + } + + info("Sending iBoot additional firmware files\n"); + + plist_dict_set_item(dict, "AdditionalBootImages", firmware_files); + restored_send(client->restore->client, dict); + plist_free(dict); + + return 0; +} + +int restore_send_recovery_os_image(struct idevicerestore_client_t* client, plist_t message) +{ + const char* component = "OS"; + char* path = NULL; + if (build_identity_get_component_path(client->recovery_variant, component, &path) < 0) { + error("ERROR: Unable to find %s path from build identity\n", component); + return -1; + } + if (!path) { + error("ERROR: Failed to get path for component %s\n", component); + return -1; + } + + uint64_t fsize = 0; + ipsw_get_file_size(client->ipsw, path, &fsize); + + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + + info("Sending %s now (%" PRIu64 " bytes)\n", component, fsize); + + struct _restore_send_file_data_ctx rctx; + rctx.client = client; + rctx.service = service; + rctx.last_progress = 0; + + if (ipsw_extract_send(client->ipsw, path, 8192, (ipsw_send_cb)_restore_send_file_data, &rctx) < 0) { + free(path); + _restore_service_free(service); + error("ERROR: Failed to send component %s\n", component); + return -1; + } + free(path); + + _restore_service_free(service); + + info("Done sending %s\n", component); + + return 0; +} + +int restore_send_recovery_os_version_data(struct idevicerestore_client_t* client, plist_t message) +{ + plist_t build_id_info = plist_dict_get_item(client->recovery_variant, "Info"); + if (!build_id_info) { + error("ERROR: Missing Info dictionary in build identity?!\n"); + return -1; + } + plist_t version_data = plist_new_dict(); + plist_dict_copy_item(version_data, build_id_info, "BuildNumber", NULL); + plist_dict_copy_item(version_data, build_id_info, "Variant", NULL); + plist_dict_copy_item(version_data, build_id_info, "BuildTrain", NULL); + plist_dict_copy_item(version_data, build_id_info, "ProductVersion", "ProductMarketingVersion"); + char *xml = NULL; + uint32_t xml_len = 0; + plist_to_xml(version_data, &xml, &xml_len); + plist_free(version_data); + + info("Sending RecoveryOS version data\n"); + + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "RecoveryOSVersionData", plist_new_data(xml, xml_len)); + plist_mem_free(xml); + restored_send(client->restore->client, dict); + plist_free(dict); + + return 0; +} + int restore_handle_data_request_msg(struct idevicerestore_client_t* client, plist_t message) { plist_t node = NULL; @@ -4702,6 +4929,34 @@ debug("%s: type = %s\n", __func__, type); } } + else if (!strcmp(type, "RecoveryOSFileAssetImage")) { + if (restore_send_recovery_os_file_asset_image(client, message) < 0) { + error("ERROR: Unable to send RecoveryOSFileImageAssetImage data\n"); + return -1; + } + } + + else if (!strcmp(type, "RecoveryOSIBootFWFilesImages")) { + if (restore_send_recovery_os_iboot_fw_files_images(client, message) < 0) { + error("ERROR: Unable to send RecoveryOSIBootFWFilesImages data\n"); + return -1; + } + } + + else if (!strcmp(type, "RecoveryOSImage")) { + if (restore_send_recovery_os_image(client, message) < 0) { + error("ERROR: Unable to send RecoveryOSImage data\n"); + return -1; + } + } + + else if (!strcmp(type, "RecoveryOSVersionData")) { + if (restore_send_recovery_os_version_data(client, message) < 0) { + error("ERROR: Unable to send RecoveryOSVersionData data\n"); + return -1; + } + } + else { // Unknown DataType!! error("Unknown data request '%s' received\n", type); @@ -4776,10 +5031,70 @@ static int restore_handle_restore_attestation(struct idevicerestore_client_t* cl return 0; } +static void _restore_calculate_recovery_os_partition_size(struct idevicerestore_client_t* client, uint64_t* min_size, uint64_t* max_size) +{ + const char* asset_list[] = { "OS", "KernelCache", "DeviceTree", "iBEC", "AppleLogo", "StaticTrustCache", "iBootData", "Diags", "Ap,SystemVolumeCanonicalMetadata", "SystemVolume", "BaseSystemVolume", "Ap,BaseSystemTrustCache", "AVISP1,RTKitOS", NULL }; + + if (min_size) *min_size = 356; + if (max_size) *max_size = 420; + + double total_size = 0; + plist_t firmware_items = plist_new_dict(); + plist_t build_id_manifest = plist_dict_get_item(client->recovery_variant, "Manifest"); + plist_dict_iter iter = NULL; + plist_dict_new_iter(build_id_manifest, &iter); + if (iter) { + char *component = NULL; + plist_t manifest_entry; + do { + component = NULL; + manifest_entry = NULL; + plist_dict_next_item(build_id_manifest, iter, &component, &manifest_entry); + if (component && PLIST_IS_DICT(manifest_entry) && plist_dict_get_item(firmware_items, component) == NULL) { + int add_image = 0; + int i = 0; + while (asset_list[i]) { + if (!strcmp(asset_list[i], component)) { + add_image = 1; + break; + } + i++; + } + plist_t fw_node; + fw_node = plist_access_path(manifest_entry, 2, "Info", "IsLoadedByiBoot"); + if (fw_node && plist_get_node_type(fw_node) == PLIST_BOOLEAN) { + uint8_t loaded_by_iboot = 0; + plist_get_bool_val(fw_node, &loaded_by_iboot); + if (loaded_by_iboot) { + add_image = 1; + } + } + if (add_image) { + plist_t p_path = plist_access_path(manifest_entry, 2, "Info", "Path"); + if (p_path) { + const char* path = plist_get_string_ptr(p_path, NULL); + uint64_t fsize = 0; + if (ipsw_get_file_size(client->ipsw, path, &fsize) == 0) { + debug("%s: Adding %s (%s, %llu bytes)\n", __func__, component, path, fsize); + total_size += (double)fsize / 0x100000; + } + } + } + } + free(component); + } while (manifest_entry); + plist_mem_free(iter); + } + total_size = ceil(total_size); + if (min_size) *min_size = total_size * 1.05 + 25; + if (max_size) *max_size = total_size * 1.25 + 25; +} + // Extracted from ac2 plist_t restore_supported_data_types() { plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "AuthInstallCACert", plist_new_bool(1)); plist_dict_set_item(dict, "BasebandBootData", plist_new_bool(0)); plist_dict_set_item(dict, "BasebandData", plist_new_bool(0)); plist_dict_set_item(dict, "BasebandStackData", plist_new_bool(0)); @@ -4797,20 +5112,26 @@ plist_t restore_supported_data_types() plist_dict_set_item(dict, "FileData", plist_new_bool(0)); plist_dict_set_item(dict, "FileDataDone", plist_new_bool(0)); plist_dict_set_item(dict, "FirmwareUpdaterData", plist_new_bool(0)); + plist_dict_set_item(dict, "FirmwareUpdaterDataV2", plist_new_bool(0)); + plist_dict_set_item(dict, "FirmwareUpdaterDataV3", plist_new_bool(1)); + plist_dict_set_item(dict, "FirmwareUpdaterPreflight", plist_new_bool(1)); plist_dict_set_item(dict, "GrapeFWData", plist_new_bool(0)); plist_dict_set_item(dict, "HPMFWData", plist_new_bool(0)); plist_dict_set_item(dict, "HostSystemTime", plist_new_bool(1)); plist_dict_set_item(dict, "KernelCache", plist_new_bool(0)); + plist_dict_set_item(dict, "MessageUseStreamedImageFile", plist_new_bool(1)); plist_dict_set_item(dict, "NORData", plist_new_bool(0)); plist_dict_set_item(dict, "NitrogenFWData", plist_new_bool(1)); plist_dict_set_item(dict, "OpalFWData", plist_new_bool(0)); plist_dict_set_item(dict, "OverlayRootDataCount", plist_new_bool(0)); plist_dict_set_item(dict, "OverlayRootDataForKey", plist_new_bool(1)); + plist_dict_set_item(dict, "OverlayRootDataForKeyIndex", plist_new_bool(1)); plist_dict_set_item(dict, "PeppyFWData", plist_new_bool(1)); plist_dict_set_item(dict, "PersonalizedBootObjectV3", plist_new_bool(0)); plist_dict_set_item(dict, "PersonalizedData", plist_new_bool(1)); plist_dict_set_item(dict, "ProvisioningData", plist_new_bool(0)); plist_dict_set_item(dict, "RamdiskFWData", plist_new_bool(1)); + plist_dict_set_item(dict, "ReceiptManifest", plist_new_bool(1)); plist_dict_set_item(dict, "RecoveryOSASRImage", plist_new_bool(1)); plist_dict_set_item(dict, "RecoveryOSAppleLogo", plist_new_bool(1)); plist_dict_set_item(dict, "RecoveryOSDeviceTree", plist_new_bool(1)); @@ -4824,6 +5145,7 @@ plist_t restore_supported_data_types() plist_dict_set_item(dict, "RecoveryOSRootTicketData", plist_new_bool(1)); plist_dict_set_item(dict, "RecoveryOSStaticTrustCache", plist_new_bool(1)); plist_dict_set_item(dict, "RecoveryOSVersionData", plist_new_bool(1)); + plist_dict_set_item(dict, "RestoreLocalPolicy", plist_new_bool(1)); plist_dict_set_item(dict, "RootData", plist_new_bool(0)); plist_dict_set_item(dict, "RootTicket", plist_new_bool(0)); plist_dict_set_item(dict, "S3EOverride", plist_new_bool(0)); @@ -4834,18 +5156,10 @@ plist_t restore_supported_data_types() plist_dict_set_item(dict, "SystemImageCanonicalMetadata", plist_new_bool(0)); plist_dict_set_item(dict, "SystemImageData", plist_new_bool(0)); plist_dict_set_item(dict, "SystemImageRootHash", plist_new_bool(0)); + plist_dict_set_item(dict, "URLAsset", plist_new_bool(1)); plist_dict_set_item(dict, "USBCFWData", plist_new_bool(0)); plist_dict_set_item(dict, "USBCOverride", plist_new_bool(0)); - plist_dict_set_item(dict, "FirmwareUpdaterPreflight", plist_new_bool(1)); - plist_dict_set_item(dict, "ReceiptManifest", plist_new_bool(1)); - plist_dict_set_item(dict, "FirmwareUpdaterDataV2", plist_new_bool(0)); - plist_dict_set_item(dict, "RestoreLocalPolicy", plist_new_bool(1)); - plist_dict_set_item(dict, "AuthInstallCACert", plist_new_bool(1)); - plist_dict_set_item(dict, "OverlayRootDataForKeyIndex", plist_new_bool(1)); - plist_dict_set_item(dict, "FirmwareUpdaterDataV3", plist_new_bool(1)); - plist_dict_set_item(dict, "MessageUseStreamedImageFile", plist_new_bool(1)); plist_dict_set_item(dict, "UpdateVolumeOverlayRootDataCount", plist_new_bool(1)); - plist_dict_set_item(dict, "URLAsset", plist_new_bool(1)); return dict; } @@ -4853,8 +5167,11 @@ plist_t restore_supported_data_types() plist_t restore_supported_message_types() { plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "AsyncDataRequestMsg", plist_new_bool(1)); + plist_dict_set_item(dict, "AsyncWait", plist_new_bool(1)); plist_dict_set_item(dict, "BBUpdateStatusMsg", plist_new_bool(0)); plist_dict_set_item(dict, "CheckpointMsg", plist_new_bool(1)); + plist_dict_set_item(dict, "CrashLog", plist_new_bool(1)); plist_dict_set_item(dict, "DataRequestMsg", plist_new_bool(0)); plist_dict_set_item(dict, "FDRSubmit", plist_new_bool(1)); plist_dict_set_item(dict, "MsgType", plist_new_bool(0)); @@ -4864,11 +5181,9 @@ plist_t restore_supported_message_types() plist_dict_set_item(dict, "ProvisioningInfo", plist_new_bool(0)); plist_dict_set_item(dict, "ProvisioningStatusMsg", plist_new_bool(0)); plist_dict_set_item(dict, "ReceivedFinalStatusMsg", plist_new_bool(0)); + plist_dict_set_item(dict, "RestoreAttestation", plist_new_bool(1)); plist_dict_set_item(dict, "RestoredCrash", plist_new_bool(1)); plist_dict_set_item(dict, "StatusMsg", plist_new_bool(0)); - plist_dict_set_item(dict, "AsyncDataRequestMsg", plist_new_bool(1)); - plist_dict_set_item(dict, "AsyncWait", plist_new_bool(1)); - plist_dict_set_item(dict, "RestoreAttestation", plist_new_bool(1)); return dict; } @@ -5024,15 +5339,15 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit //plist_dict_set_item(opts, "AuthInstallRestoreBehavior", plist_new_string("Erase")); plist_dict_set_item(opts, "AutoBootDelay", plist_new_uint(0)); - if (client->preflight_info) { - plist_t bbus = plist_copy(client->preflight_info); + if (client->firmware_preflight_info) { + plist_t bbus = plist_copy(client->firmware_preflight_info); plist_dict_remove_item(bbus, "FusingStatus"); plist_dict_remove_item(bbus, "PkHash"); plist_dict_set_item(opts, "BBUpdaterState", bbus); - plist_dict_copy_data(opts, client->preflight_info, "BasebandNonce", "Nonce"); + plist_dict_copy_data(opts, client->firmware_preflight_info, "BasebandNonce", "Nonce"); } plist_dict_set_item(opts, "SupportedDataTypes", restore_supported_data_types()); @@ -5078,7 +5393,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit } } else { // FIXME: new on iOS 5 ? - plist_dict_set_item(opts, "BootImageType", plist_new_string("UserOrInternal")); + plist_dict_set_item(opts, "BootImageType", plist_new_string("User")); // FIXME: required? //plist_dict_set_item(opts, "BootImageFile", plist_new_string("018-7923-347.dmg")); plist_dict_set_item(opts, "DFUFileType", plist_new_string("RELEASE")); @@ -5104,7 +5419,27 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit // FIXME: new on iOS 5 ? plist_dict_set_item(opts, "SystemImageType", plist_new_string("User")); // FIXME: does this have any effect actually? - plist_dict_set_item(opts, "UpdateBaseband", plist_new_bool(0)); + plist_dict_set_item(opts, "UpdateBaseband", plist_new_bool(1)); + plist_dict_set_item(opts, "InstallDiags", plist_new_bool(0)); + if (client->recovery_variant) { + plist_dict_set_item(opts, "InstallRecoveryOS", plist_new_bool(1)); + plist_dict_set_item(opts, "RecoveryOSBundlePath", plist_new_string("/tmp/Per2.tmp")); + plist_t recovery_variant = plist_access_path(client->recovery_variant, 2, "Info", "Variant"); + plist_dict_set_item(opts, "AuthInstallRecoveryOSVariant", plist_copy(recovery_variant)); + uint64_t max_size = 0; + uint64_t min_size = 0; + _restore_calculate_recovery_os_partition_size(client, &min_size, &max_size); + info("Calculated recoveryOSPartitionSize as %" PRIu64 " MB\n", min_size); + info("Calculated recoveryOSMaxPartitionSize as %" PRIu64 " MB\n", max_size); + plist_dict_set_item(opts, "recoveryOSMaxPartitionSize", plist_new_uint(max_size)); + plist_dict_set_item(opts, "recoveryOSPartitionSize", plist_new_uint(min_size)); + } + + if (plist_dict_get_bool(client->parameters, "RequiresNonceSlot")) { + info("Device will use nonce slots.\n"); + } else { + info("Device will not use nonce slots.\n"); + } // Added for iOS 18.0 beta 1 plist_dict_set_item(opts, "HostHasFixFor99053849", plist_new_bool(1)); @@ -5154,10 +5489,14 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit spp = plist_copy(spp); } else { spp = plist_new_dict(); + plist_dict_set_item(spp, "1024", plist_new_uint(1280)); plist_dict_set_item(spp, "128", plist_new_uint(1280)); plist_dict_set_item(spp, "16", plist_new_uint(160)); + plist_dict_set_item(spp, "256", plist_new_uint(1280)); plist_dict_set_item(spp, "32", plist_new_uint(320)); + plist_dict_set_item(spp, "512", plist_new_uint(1280)); plist_dict_set_item(spp, "64", plist_new_uint(640)); + plist_dict_set_item(spp, "768", plist_new_uint(1280)); plist_dict_set_item(spp, "8", plist_new_uint(80)); } plist_dict_set_item(opts, "SystemPartitionPadding", spp); |