diff options
Diffstat (limited to 'src/idevicerestore.c')
-rw-r--r-- | src/idevicerestore.c | 228 |
1 files changed, 1 insertions, 227 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 0726285..56bc44a 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -26,7 +26,6 @@ #include <getopt.h> #include <plist/plist.h> #include <zlib.h> -#include <openssl/sha.h> #include "dfu.h" #include "tss.h" @@ -139,165 +138,6 @@ static int load_version_data(struct idevicerestore_client_t* client) return 0; } -int get_latest_fw(struct idevicerestore_client_t* client, char** fwurl, unsigned char* sha1buf) -{ - *fwurl = NULL; - memset(sha1buf, '\0', 20); - - plist_t n1 = plist_access_path(client->version_data, 2, "MobileDeviceMajorVersionsByProductType", client->device->product); - if (!n1 || (plist_dict_get_size(n1) == 0)) { - error("%s: ERROR: Can't find MobileDeviceMajorVersionsByProductType/%s dict in version data\n", __func__, client->device->product); - return -1; - } - - char* strval = NULL; - plist_t n2 = plist_dict_get_item(n1, "SameAs"); - if (n2) { - plist_get_string_val(n2, &strval); - } - if (strval) { - n1 = plist_access_path(client->version_data, 2, "MobileDeviceMajorVersionsByProductType", strval); - free(strval); - strval = NULL; - if (!n1 || (plist_dict_get_size(n1) == 0)) { - error("%s: ERROR: Can't find MobileDeviceMajorVersionsByProductType/%s dict in version data\n", __func__, client->device->product); - return -1; - } - } - - plist_dict_iter iter = NULL; - plist_dict_new_iter(n1, &iter); - if (!iter) { - error("%s: ERROR: Can't get dict iter\n", __func__); - return -1; - } - n2 = NULL; - char* key = NULL; - plist_t val = NULL; - do { - plist_dict_next_item(n1, iter, &key, &val); - if (key) { - n2 = val; - free(key); - } - } while (val); - free(iter); - - if (!n2) { - error("%s: ERROR: Can't get last node?!\n", __func__); - return -1; - } - - uint64_t major = 0; - if (plist_get_node_type(n2) == PLIST_ARRAY) { - uint32_t sz = plist_array_get_size(n2); - plist_t n3 = plist_array_get_item(n2, sz-1); - plist_get_uint_val(n3, &major); - } else { - plist_get_uint_val(n2, &major); - } - - if (major == 0) { - error("%s: ERROR: Can't find major version?!\n", __func__); - return -1; - } - - char majstr[32]; // should be enough for a uint64_t value - sprintf(majstr, FMT_qu, (long long unsigned int)major); - n1 = plist_access_path(client->version_data, 7, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", client->device->product, "Unknown", "Universal", "Restore"); - if (!n1) { - error("%s: ERROR: Can't get Unknown/Universal/Restore node?!\n", __func__); - return -1; - } - - n2 = plist_dict_get_item(n1, "BuildVersion"); - if (!n2 || (plist_get_node_type(n2) != PLIST_STRING)) { - error("%s: ERROR: Can't get build version node?!\n", __func__); - return -1; - } - - strval = NULL; - plist_get_string_val(n2, &strval); - - n1 = plist_access_path(client->version_data, 5, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", client->device->product, strval); - if (!n1) { - error("%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s node?!\n", __func__, strval); - free(strval); - return -1; - } - free(strval); - - strval = NULL; - n2 = plist_dict_get_item(n1, "SameAs"); - if (n2) { - plist_get_string_val(n2, &strval); - } - if (strval) { - n1 = plist_access_path(client->version_data, 5, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", client->device->product, strval); - free(strval); - strval = NULL; - if (!n1 || (plist_dict_get_size(n1) == 0)) { - error("%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s dict\n", __func__, client->device->product); - return -1; - } - } - - n2 = plist_access_path(n1, 2, "Update", "BuildVersion"); - if (n2) { - strval = NULL; - plist_get_string_val(n2, &strval); - if (strval) { - n1 = plist_access_path(client->version_data, 5, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", client->device->product, strval); - free(strval); - strval = NULL; - } - } - - n2 = plist_access_path(n1, 2, "Restore", "FirmwareURL"); - if (!n2 || (plist_get_node_type(n2) != PLIST_STRING)) { - error("%s: ERROR: Can't get FirmwareURL node\n", __func__); - return -1; - } - - plist_get_string_val(n2, fwurl); - - n2 = plist_access_path(n1, 2, "Restore", "FirmwareSHA1"); - if (n2 && plist_get_node_type(n2) == PLIST_STRING) { - strval = NULL; - plist_get_string_val(n2, &strval); - if (strval) { - if (strlen(strval) == 40) { - int i; - int v; - for (i = 0; i < 40; i+=2) { - v = 0; - sscanf(strval+i, "%02x", &v); - sha1buf[i/2] = (unsigned char)v; - } - } - free(strval); - } - } - - return 0; -} - -static int sha1_verify_fp(FILE* f, unsigned char* expected_sha1) -{ - unsigned char tsha1[20]; - char buf[8192]; - if (!f) return 0; - SHA_CTX sha1ctx; - SHA1_Init(&sha1ctx); - rewind(f); - while (!feof(f)) { - size_t sz = fread(buf, 1, 8192, f); - SHA1_Update(&sha1ctx, (const void*)buf, sz); - } - SHA1_Final(tsha1, &sha1ctx); - return (memcmp(expected_sha1, tsha1, 20) == 0) ? 1 : 0; -} - int main(int argc, char* argv[]) { int opt = 0; int optindex = 0; @@ -510,77 +350,11 @@ int main(int argc, char* argv[]) { } if (latest) { - char* fwurl = NULL; - unsigned char isha1[20]; - if ((get_latest_fw(client, &fwurl, isha1) < 0) || !fwurl) { - error("ERROR: can't get URL for latest firmware\n"); - return -1; - } - char* fwfn = strrchr(fwurl, '/'); - if (!fwfn) { - error("ERROR: can't get local filename for firmware ipsw\n"); - return -1; - } - fwfn++; - - info("Latest firmware is %s\n", fwfn); - - char fwlfn[256]; - sprintf(fwlfn, "cache/%s", fwfn); - - int need_dl = 0; - unsigned char zsha1[20] = {0, }; - FILE* f = fopen(fwlfn, "rb"); - if (f) { - if (memcmp(zsha1, isha1, 20) != 0) { - info("Verifying '%s'...\n", fwlfn); - if (sha1_verify_fp(f, isha1)) { - info("Checksum matches.\n"); - } else { - info("Checksum does not match.\n"); - need_dl = 1; - } - } - fclose(f); - } else { - need_dl = 1; - } - - int res = 0; - if (need_dl) { - if (strncmp(fwurl, "protected:", 10) == 0) { - error("ERROR: Can't download '%s' because it needs a purchase.\n", fwfn); - res = -1; - } else { - remove(fwlfn); - info("Downloading latest firmware (%s)\n", fwurl); - download_to_file(fwurl, fwlfn); - if (memcmp(isha1, zsha1, 20) != 0) { - info("\nVerifying '%s'...\n", fwlfn); - FILE* f = fopen(fwlfn, "rb"); - if (f) { - if (sha1_verify_fp(f, isha1)) { - info("Checksum matches.\n"); - } else { - error("ERROR: File download failed (checksum mismatch).\n"); - res = -1; - } - fclose(f); - } else { - error("ERROR: Can't open '%s' for checksum verification\n", fwlfn); - res = -1; - } - } - } - } - + int res = ipsw_download_latest_fw(client->version_data, client->device->product, "cache", &ipsw); if (res != 0) { - free(fwurl); return res; } else { - ipsw = strdup(fwlfn); client->ipsw = ipsw; - free(fwurl); } } |