diff options
-rw-r--r-- | src/common.h | 8 | ||||
-rw-r--r-- | src/dfu.c | 17 | ||||
-rw-r--r-- | src/dfu.h | 1 | ||||
-rw-r--r-- | src/idevicerestore.c | 24 | ||||
-rw-r--r-- | src/idevicerestore.h | 1 | ||||
-rw-r--r-- | src/normal.c | 45 | ||||
-rw-r--r-- | src/normal.h | 1 | ||||
-rw-r--r-- | src/recovery.c | 16 | ||||
-rw-r--r-- | src/recovery.h | 1 |
9 files changed, 113 insertions, 1 deletions
diff --git a/src/common.h b/src/common.h index a634e6f..2ea4a91 100644 --- a/src/common.h +++ b/src/common.h @@ -42,6 +42,13 @@ extern "C" { #define FLAG_QUIT 1 +#define CPFM_FLAG_SECURITY_MODE 1 << 0 +#define CPFM_FLAG_PRODUCTION_MODE 1 << 1 + +#define IBOOT_FLAG_IMAGE4_AWARE 1 << 2 +#define IBOOT_FLAG_EFFECTIVE_SECURITY_MODE 1 << 3 +#define IBOOT_FLAG_EFFECTIVE_PRODUCTION_MODE 1 << 4 + struct dfu_client_t; struct normal_client_t; struct restore_client_t; @@ -70,6 +77,7 @@ struct idevicerestore_client_t { uint64_t ecid; unsigned char* nonce; int nonce_size; + int image4supported; char* udid; char* srnm; char* ipsw; @@ -241,6 +241,22 @@ int dfu_get_cpid(struct idevicerestore_client_t* client, unsigned int* cpid) { return 0; } +int dfu_is_image4_supported(struct idevicerestore_client_t* client) +{ + if(client->dfu == NULL) { + if (dfu_client_new(client) < 0) { + return 0; + } + } + + const struct irecv_device_info *device_info = irecv_get_device_info(client->dfu->client); + if (!device_info) { + return 0; + } + + return (device_info->ibfl & IBOOT_FLAG_IMAGE4_AWARE); +} + int dfu_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size) { irecv_error_t dfu_error = IRECV_E_SUCCESS; @@ -250,7 +266,6 @@ int dfu_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** non } } - const struct irecv_device_info *device_info = irecv_get_device_info(client->dfu->client); if (!device_info) { return -1; @@ -44,6 +44,7 @@ const char* dfu_check_product_type(struct idevicerestore_client_t* client); int dfu_send_buffer(struct idevicerestore_client_t* client, unsigned char* buffer, unsigned int size); int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component); int dfu_get_cpid(struct idevicerestore_client_t* client, unsigned int* cpid); +int dfu_is_image4_supported(struct idevicerestore_client_t* client); int dfu_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); int dfu_get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity); diff --git a/src/idevicerestore.c b/src/idevicerestore.c index e9580bd..a0f5a87 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -365,6 +365,9 @@ int idevicerestore_start(struct idevicerestore_client_t* client) info("Product Version: %s\n", client->version); info("Product Build: %s Major: %d\n", client->build, client->build_major); + client->image4supported = is_image4_supported(client); + info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false"); + if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; @@ -1182,6 +1185,27 @@ const char* check_product_type(struct idevicerestore_client_t* client) { return product_type; } +int is_image4_supported(struct idevicerestore_client_t* client) +{ + int res = 0; + + switch (client->mode->index) { + case MODE_NORMAL: + res = normal_is_image4_supported(client); + break; + case MODE_DFU: + res = dfu_is_image4_supported(client); + break; + case MODE_RECOVERY: + res = recovery_is_image4_supported(client); + break; + default: + error("ERROR: Device is in an invalid state\n"); + return 0; + } + return res; +} + int get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid) { switch (client->mode->index) { case MODE_NORMAL: diff --git a/src/idevicerestore.h b/src/idevicerestore.h index c7ac7f9..f646d4a 100644 --- a/src/idevicerestore.h +++ b/src/idevicerestore.h @@ -75,6 +75,7 @@ void usage(int argc, char* argv[]); int check_mode(struct idevicerestore_client_t* client); const char* check_product_type(struct idevicerestore_client_t* client); int get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid); +int is_image4_supported(struct idevicerestore_client_t* client); int get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); int get_shsh_blobs(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss); void fixup_tss(plist_t tss); diff --git a/src/normal.c b/src/normal.c index 15bbc01..3b536ed 100644 --- a/src/normal.c +++ b/src/normal.c @@ -391,6 +391,51 @@ int normal_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** return normal_get_nonce_by_key(client, "SEPNonce", nonce, nonce_size); } +int normal_is_image4_supported(struct idevicerestore_client_t* client) +{ + idevice_t device = NULL; + plist_t node = NULL; + lockdownd_client_t lockdown = NULL; + idevice_error_t device_error = IDEVICE_E_SUCCESS; + lockdownd_error_t lockdown_error = IDEVICE_E_SUCCESS; + + device_error = idevice_new(&device, client->udid); + if (device_error != IDEVICE_E_SUCCESS) { + return 0; + } + + lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore"); + if (lockdown_error != LOCKDOWN_E_SUCCESS) { + error("ERROR: Unable to connect to lockdownd\n"); + idevice_free(device); + return 0; + } + + lockdown_error = lockdownd_get_value(lockdown, NULL, "Image4Supported", &node); + if (lockdown_error != LOCKDOWN_E_SUCCESS) { + lockdownd_client_free(lockdown); + idevice_free(device); + return 0; + } + + if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) { + lockdownd_client_free(lockdown); + idevice_free(device); + return 0; + } + + uint8_t bval = 0; + plist_get_bool_val(node, &bval); + plist_free(node); + + lockdownd_client_free(lockdown); + idevice_free(device); + lockdown = NULL; + device = NULL; + + return bval; +} + int normal_get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid) { idevice_t device = NULL; plist_t unique_chip_node = NULL; diff --git a/src/normal.h b/src/normal.h index 892747a..abc4fe1 100644 --- a/src/normal.h +++ b/src/normal.h @@ -47,6 +47,7 @@ void normal_client_free(struct idevicerestore_client_t* client); int normal_open_with_timeout(struct idevicerestore_client_t* client); int normal_enter_recovery(struct idevicerestore_client_t* client); int normal_get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid); +int normal_is_image4_supported(struct idevicerestore_client_t* client); int normal_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); int normal_get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); diff --git a/src/recovery.c b/src/recovery.c index f2104b7..9221dda 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -461,6 +461,22 @@ int recovery_get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid) { return 0; } +int recovery_is_image4_supported(struct idevicerestore_client_t* client) +{ + if(client->recovery == NULL) { + if (recovery_client_new(client) < 0) { + return 0; + } + } + + const struct irecv_device_info *device_info = irecv_get_device_info(client->recovery->client); + if (!device_info) { + return 0; + } + + return (device_info->ibfl & IBOOT_FLAG_IMAGE4_AWARE); +} + int recovery_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size) { irecv_error_t recovery_error = IRECV_E_SUCCESS; diff --git a/src/recovery.h b/src/recovery.h index 8deb438..7da2432 100644 --- a/src/recovery.h +++ b/src/recovery.h @@ -54,6 +54,7 @@ int recovery_send_reset(struct idevicerestore_client_t* client); int recovery_send_ticket(struct idevicerestore_client_t* client); int recovery_set_autoboot(struct idevicerestore_client_t* client, int enable); int recovery_get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid); +int recovery_is_image4_supported(struct idevicerestore_client_t* client); int recovery_get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); int recovery_get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size); |