diff --git a/external/idevicerestore b/external/idevicerestore index 6f78f57c..b3ac88e2 160000 --- a/external/idevicerestore +++ b/external/idevicerestore @@ -1 +1 @@ -Subproject commit 6f78f57cd825c84c872af4615da09de59cb8830e +Subproject commit b3ac88e2c5c6faeab88eca86bb4ff0f94972d0f7 diff --git a/futurerestore/futurerestore.cpp b/futurerestore/futurerestore.cpp index 0a44f7d8..9113ab6d 100644 --- a/futurerestore/futurerestore.cpp +++ b/futurerestore/futurerestore.cpp @@ -7,12 +7,10 @@ // #include -#include -#include -#include -#include #include #include +#include +#include #include "futurerestore.hpp" #ifdef HAVE_LIBIPATCHER @@ -20,9 +18,8 @@ #endif #include -#include -extern "C"{ +extern "C" { #include "common.h" #include "normal.h" #include "recovery.h" @@ -30,26 +27,26 @@ extern "C"{ #include "ipsw.h" #include "locking.h" #include "restore.h" +#include "endianness.h" #include "tsschecker.h" -#include -#include "../external/idevicerestore/src/endianness.h" } -//(re)define __mkdir -#ifdef __mkdir -#undef __mkdir +#ifdef safe_mkdir +#undef safe_mkdir #endif #ifdef WIN32 #include -#define __mkdir(path, mode) mkdir(path) +#define safe_mkdir(path, mode) mkdir(path) #else + #include + #ifdef __APPLE__ #define NEW_ID 501 #else #define NEW_ID 1000 #endif -#define __mkdir(path, mode) \ +#define safe_mkdir(path, mode) \ do { \ int id = getuid(); \ setuid(NEW_ID); \ @@ -67,33 +64,25 @@ do { \ #define USEC_PER_SEC 1000000 #ifdef WIN32 -#define FUTURERESTORE_TMP_PATH "download" +std::string futurerestoreTempPath(download"); #else -#define TMP_PATH "/tmp" -#define FUTURERESTORE_TMP_PATH TMP_PATH"/futurerestore" +std::string tempPath("/tmp"); +std::string futurerestoreTempPath(tempPath + "/futurerestore"); #endif -#define ROSE_TMP_PATH FUTURERESTORE_TMP_PATH"/rose.bin" -#define SE_TMP_PATH FUTURERESTORE_TMP_PATH"/se.sefw" - -#define SAVAGE_B0_PP_TMP_PATH FUTURERESTORE_TMP_PATH"/savageB0PP.fw" -#define SAVAGE_B0_DP_TMP_PATH FUTURERESTORE_TMP_PATH"/savageB0DP.fw" - -#define SAVAGE_B2_PP_TMP_PATH FUTURERESTORE_TMP_PATH"/savageB2PP.fw" -#define SAVAGE_B2_DP_TMP_PATH FUTURERESTORE_TMP_PATH"/savageB2DP.fw" - -#define SAVAGE_BA_PP_TMP_PATH FUTURERESTORE_TMP_PATH"/savageBAPP.fw" -#define SAVAGE_BA_DP_TMP_PATH FUTURERESTORE_TMP_PATH"/savageBADP.fw" - -#define VERIDIAN_DGM_TMP_PATH FUTURERESTORE_TMP_PATH"/veridianDGM.der" -#define VERIDIAN_FWM_TMP_PATH FUTURERESTORE_TMP_PATH"/veridianFWM.plist" -#define BASEBAND_TMP_PATH FUTURERESTORE_TMP_PATH"/baseband.bbfw" -#define BASEBAND_MANIFEST_TMP_PATH FUTURERESTORE_TMP_PATH"/basebandManifest.plist" -#define SEP_TMP_PATH FUTURERESTORE_TMP_PATH"/sep.im4p" -#define SEP_MANIFEST_TMP_PATH FUTURERESTORE_TMP_PATH"/sepManifest.plist" +std::string roseTempPath = futurerestoreTempPath + "/rose.bin"; +std::string seTempPath = futurerestoreTempPath + "/se.sefw"; +std::string veridianDGMTempPath = futurerestoreTempPath + "/veridianDGM.der"; +std::string veridianFWMTempPath = futurerestoreTempPath + "/veridianFWM.plist"; +std::string basebandTempPath = futurerestoreTempPath + "/baseband.bbfw"; +std::string basebandManifestTempPath = futurerestoreTempPath + "/basebandManifest.plist"; +std::string sepTempPath = futurerestoreTempPath + "/sep.im4p"; +std::string sepManifestTempPath = futurerestoreTempPath + "/sepManifest.plist"; #ifdef __APPLE__ + # include + # define SHA1(d, n, md) CC_SHA1(d, n, md) # define SHA384(d, n, md) CC_SHA384(d, n, md) #else @@ -107,290 +96,289 @@ do { \ using namespace tihmstar; #pragma mark helpers -extern "C"{ - void irecv_event_cb(const irecv_device_event_t* event, void *userdata); - void idevice_event_cb(const idevice_event_t *event, void *userdata); - int dfu_send_iboot_stage1_components(struct idevicerestore_client_t* client, plist_t build_identity); - int dfu_send_command(struct idevicerestore_client_t* client, const char* command); - int dfu_send_component_and_command(struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* command); - irecv_error_t irecv_send_command(irecv_client_t client, const char* command); - int recovery_send_component_and_command(struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* command); - int recovery_send_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component); +extern "C" { +void irecv_event_cb(const irecv_device_event_t *event, void *userdata); +void idevice_event_cb(const idevice_event_t *event, void *userdata); } #pragma mark futurerestore -futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, bool setNonce, bool serial, bool noRestore) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu), _noIBSS(noIBSS), _setNonce(setNonce), _serial(serial), _noRestore(noRestore){ + +futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, bool setNonce, bool serial, + bool noRestore) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu), _noIBSS(noIBSS), + _setNonce(setNonce), _serial(serial), _noRestore(noRestore) { _client = idevicerestore_client_new(); - if (_client == NULL) throw std::string("could not create idevicerestore client\n"); - + retassure(_client != nullptr, "could not create idevicerestore client\n"); + struct stat st{0}; - if (stat(FUTURERESTORE_TMP_PATH, &st) == -1) __mkdir(FUTURERESTORE_TMP_PATH, 0755); + if (stat(futurerestoreTempPath.c_str(), &st) == -1) safe_mkdir(futurerestoreTempPath.c_str(), 0755); nocache = 1; //tsschecker nocache _foundnonce = -1; } -bool futurerestore::init(){ +bool futurerestore::init() { if (_didInit) return _didInit; // If device is in an invalid state, don't check if it supports img4 if ((_didInit = check_mode(_client) != _MODE_UNKNOWN)) { - if (!(_client->image4supported = is_image4_supported(_client))){ + if (!(_client->image4supported = is_image4_supported(_client))) { info("[INFO] 32-bit device detected\n"); - }else{ + } else { info("[INFO] 64-bit device detected\n"); } } return _didInit; } -uint64_t futurerestore::getDeviceEcid(){ +uint64_t futurerestore::getDeviceEcid() { retassure(_didInit, "did not init\n"); uint64_t ecid; get_ecid(_client, &ecid); return ecid; } -int futurerestore::getDeviceMode(bool reRequest){ +int futurerestore::getDeviceMode(bool reRequest) { retassure(_didInit, "did not init\n"); if (!reRequest && _client->mode && _client->mode->index != _MODE_UNKNOWN) { return _client->mode->index; - }else{ + } else { dfu_client_free(_client); recovery_client_free(_client); return check_mode(_client); } } -void futurerestore::putDeviceIntoRecovery(){ +void futurerestore::putDeviceIntoRecovery() { retassure(_didInit, "did not init\n"); #ifdef HAVE_LIBIPATCHER _enterPwnRecoveryRequested = _isPwnDfu; #endif - + getDeviceMode(false); info("Found device in %s mode\n", _client->mode->string); - if (_client->mode == MODE_NORMAL){ + if (_client->mode == MODE_NORMAL) { irecv_device_event_subscribe(&_client->irecv_e_ctx, irecv_event_cb, _client); idevice_event_subscribe(idevice_event_cb, _client); - _client->idevice_e_ctx = (void *)idevice_event_cb; + _client->idevice_e_ctx = (void *) idevice_event_cb; #ifdef HAVE_LIBIPATCHER retassure(!_isPwnDfu, "isPwnDfu enabled, but device was found in normal mode\n"); #endif info("Entering recovery mode...\n"); - retassure(!normal_enter_recovery(_client),"Unable to place device into recovery mode from %s mode\n", _client->mode->string); - }else if (_client->mode == MODE_RECOVERY){ + retassure(!normal_enter_recovery(_client), "Unable to place device into recovery mode from %s mode\n", + _client->mode->string); + } else if (_client->mode == MODE_RECOVERY) { info("Device already in recovery mode\n"); - }else if (_client->mode == MODE_DFU && _isPwnDfu && -#ifdef HAVE_LIBIPATCHER - true + } else if (_client->mode == MODE_DFU && _isPwnDfu && + #ifdef HAVE_LIBIPATCHER + true #else - false + false #endif - ){ + ) { info("requesting to get into pwnRecovery later\n"); - }else if (!_client->image4supported){ + } else if (!_client->image4supported) { info("32-bit device in DFU mode found, assuming user wants to use iOS 9.x re-restore bug. Not failing here\n"); - }else{ + } else { reterror("unsupported device mode, please put device in recovery or normal mode\n"); } - safeFree(_client->udid); //only needs to be freed manually when function did't throw exception - + safeFree(_client->udid); //only needs to be freed manually when function didn't throw exception + //these get also freed by destructor dfu_client_free(_client); recovery_client_free(_client); } -void futurerestore::setAutoboot(bool val){ +void futurerestore::setAutoboot(bool val) { retassure(_didInit, "did not init\n"); retassure(getDeviceMode(false) == _MODE_RECOVERY, "can't set auto-boot, when device isn't in recovery mode\n"); - if(!_client->recovery){ - retassure(!recovery_client_new(_client),"Could not connect to device in recovery mode.\n"); + if (!_client->recovery) { + retassure(!recovery_client_new(_client), "Could not connect to device in recovery mode.\n"); } - retassure(!recovery_set_autoboot(_client, val),"Setting auto-boot failed?!\n"); + retassure(!recovery_set_autoboot(_client, val), "Setting auto-boot failed?!\n"); } -void futurerestore::exitRecovery(){ +void futurerestore::exitRecovery() { setAutoboot(true); recovery_send_reset(_client); recovery_client_free(_client); } -plist_t futurerestore::nonceMatchesApTickets(){ +plist_t futurerestore::nonceMatchesApTickets() { retassure(_didInit, "did not init\n"); - if (getDeviceMode(true) != _MODE_RECOVERY){ + if (getDeviceMode(true) != _MODE_RECOVERY) { if (getDeviceMode(false) != _MODE_DFU || *_client->version != '9') reterror("Device is not in recovery mode, can't check ApNonce\n"); else - _rerestoreiOS9 = (info("Detected iOS 9.x 32-bit re-restore, proceeding in DFU mode\n"),true); + _rerestoreiOS9 = (info("Detected iOS 9.x 32-bit re-restore, proceeding in DFU mode\n"), true); } - - unsigned char* realnonce; + + unsigned char *realnonce; int realNonceSize = 0; if (_rerestoreiOS9) { info("Skipping ApNonce check\n"); - }else{ + } else { recovery_get_ap_nonce(_client, &realnonce, &realNonceSize); - + info("Got ApNonce from device: "); int i = 0; for (i = 0; i < realNonceSize; i++) { - info("%02x ", ((unsigned char *)realnonce)[i]); + info("%02x ", ((unsigned char *) realnonce)[i]); } info("\n"); } - - vectornonces; - - if (_client->image4supported){ - for (int i=0; i< _im4ms.size(); i++){ - auto nonce = img4tool::getValFromIM4M({_im4ms[i].first,_im4ms[i].second}, 'BNCH'); - if (nonce.payloadSize() == realNonceSize && memcmp(realnonce, nonce.payload(), realNonceSize) == 0) return _aptickets[i]; + + vector nonces; + + if (_client->image4supported) { + for (int i = 0; i < _im4ms.size(); i++) { + auto nonce = img4tool::getValFromIM4M({_im4ms[i].first, _im4ms[i].second}, 'BNCH'); + if (nonce.payloadSize() == realNonceSize && memcmp(realnonce, nonce.payload(), realNonceSize) == 0) + return _aptickets[i]; } - }else{ - for (int i=0; i< _im4ms.size(); i++){ + } else { + for (int i = 0; i < _im4ms.size(); i++) { size_t ticketNonceSize = 0; - const char *nonce = NULL; + const char *nonce = nullptr; try { //nonce might not exist, which we use in re-restoring iOS 9.x for 32-bit auto n = getNonceFromSCAB(_im4ms[i].first, _im4ms[i].second); ticketNonceSize = n.second; nonce = n.first; - } catch (...) - { } + } catch (...) {} if (memcmp(realnonce, nonce, ticketNonceSize) == 0 && - ( (ticketNonceSize == realNonceSize && realNonceSize+ticketNonceSize > 0) || - (!ticketNonceSize && *_client->version == '9' && - (getDeviceMode(false) == _MODE_DFU || - ( getDeviceMode(false) == _MODE_RECOVERY && !strncmp(getiBootBuild(), "iBoot-2817", strlen("iBoot-2817")) ) - ) - ) + ((ticketNonceSize == realNonceSize && realNonceSize + ticketNonceSize > 0) || + (!ticketNonceSize && *_client->version == '9' && + (getDeviceMode(false) == _MODE_DFU || + (getDeviceMode(false) == _MODE_RECOVERY && + !strncmp(getiBootBuild(), "iBoot-2817", strlen("iBoot-2817"))) + ) ) - ) + ) + ) //either nonce needs to match or using re-restore bug in iOS 9.x return _aptickets[i]; } } - - return NULL; + + return nullptr; } -std::pair futurerestore::nonceMatchesIM4Ms(){ +std::pair futurerestore::nonceMatchesIM4Ms() { retassure(_didInit, "did not init\n"); retassure(getDeviceMode(true) == _MODE_RECOVERY, "Device is not in recovery mode, can't check ApNonce\n"); - - unsigned char* realnonce; + + unsigned char *realnonce; int realNonceSize = 0; recovery_get_ap_nonce(_client, &realnonce, &realNonceSize); - - vectornonces; - + + vector nonces; + if (_client->image4supported) { - for (int i=0; i< _im4ms.size(); i++){ - auto nonce = img4tool::getValFromIM4M({_im4ms[i].first,_im4ms[i].second}, 'BNCH'); - if (nonce.payloadSize() == realNonceSize && memcmp(realnonce, nonce.payload(), realNonceSize) == 0) return _im4ms[i]; + for (auto &_im4m: _im4ms) { + auto nonce = img4tool::getValFromIM4M({_im4m.first, _im4m.second}, 'BNCH'); + if (nonce.payloadSize() == realNonceSize && memcmp(realnonce, nonce.payload(), realNonceSize) == 0) + return _im4m; } - }else{ - for (int i=0; i< _im4ms.size(); i++){ + } else { + for (auto &_im4m: _im4ms) { size_t ticketNonceSize = 0; - const char *nonce = NULL; + const char *nonce = nullptr; try { //nonce might not exist, which we use in re-restoring iOS 9.x for 32-bit - auto n = getNonceFromSCAB(_im4ms[i].first, _im4ms[i].second); + auto n = getNonceFromSCAB(_im4m.first, _im4m.second); ticketNonceSize = n.second; nonce = n.first; } catch (...) { // } - if (memcmp(realnonce, nonce, ticketNonceSize) == 0) return _im4ms[i]; + if (memcmp(realnonce, nonce, ticketNonceSize) == 0) return _im4m; } } - - return {NULL,0}; + + return {NULL, 0}; } -void futurerestore::waitForNonce(vectornonces, size_t nonceSize){ +void futurerestore::waitForNonce(vector nonces, size_t nonceSize) { retassure(_didInit, "did not init\n"); setAutoboot(false); - - unsigned char* realnonce; + + unsigned char *realnonce; int realNonceSize = 0; - - for (auto nonce : nonces){ + + for (auto nonce: nonces) { info("waiting for ApNonce: "); int i = 0; for (i = 0; i < nonceSize; i++) { - info("%02x ", ((unsigned char *)nonce)[i]); + info("%02x ", ((unsigned char *) nonce)[i]); } info("\n"); } - + do { - if (realNonceSize){ + if (realNonceSize) { recovery_send_reset(_client); recovery_client_free(_client); - usleep(1*USEC_PER_SEC); + usleep(1 * USEC_PER_SEC); } - while (getDeviceMode(true) != _MODE_RECOVERY) usleep(USEC_PER_SEC*0.5); + while (getDeviceMode(true) != _MODE_RECOVERY) usleep(USEC_PER_SEC * 0.5); retassure(!recovery_client_new(_client), "Could not connect to device in recovery mode\n"); - + recovery_get_ap_nonce(_client, &realnonce, &realNonceSize); info("Got ApNonce from device: "); - int i = 0; - for (i = 0; i < realNonceSize; i++) { + for (int i = 0; i < realNonceSize; i++) { info("%02x ", realnonce[i]); } info("\n"); - for (int i=0; inonces; - + vector nonces; + retassure(_client->image4supported, "Error: ApNonce collision function is not supported on 32-bit devices\n"); - - for (auto im4m : _im4ms){ - auto nonce = img4tool::getValFromIM4M({im4m.first,im4m.second}, 'BNCH'); + + for (auto im4m: _im4ms) { + auto nonce = img4tool::getValFromIM4M({im4m.first, im4m.second}, 'BNCH'); if (!nonceSize) { nonceSize = nonce.payloadSize(); } retassure(nonceSize == nonce.payloadSize(), "Nonces have different lengths!"); - nonces.push_back((const char*)nonce.payload()); + nonces.push_back((const char *) nonce.payload()); } - - waitForNonce(nonces,nonceSize); + + waitForNonce(nonces, nonceSize); } -void futurerestore::loadAPTickets(const vector &apticketPaths){ - for (auto apticketPath : apticketPaths){ - plist_t apticket = NULL; - char *im4m = NULL; - struct stat fst; - - retassure(!stat(apticketPath, &fst), "failed to load APTicket at %s\n",apticketPath); - +void futurerestore::loadAPTickets(const vector &apticketPaths) { + for (auto apticketPath: apticketPaths) { + plist_t apticket = nullptr; + char *im4m = nullptr; + struct stat fst{}; + + retassure(!stat(apticketPath, &fst), "failed to load APTicket at %s\n", apticketPath); + gzFile zf = gzopen(apticketPath, "rb"); if (zf) { int blen = 0; int readsize = 16384; //0x4000 int bufsize = readsize; - char* bin = (char*)malloc(bufsize); - char* p = bin; + char *bin = (char *) malloc(bufsize); + char *p = bin; do { int bytes_read = gzread(zf, p, readsize); - retassure(bytes_read>0, "Error reading gz compressed data\n"); + retassure(bytes_read > 0, "Error reading gz compressed data\n"); blen += bytes_read; if (bytes_read < readsize) { if (gzeof(zf)) { @@ -399,7 +387,7 @@ void futurerestore::loadAPTickets(const vector &apticketPaths){ } } bufsize += readsize; - bin = (char*)realloc(bin, bufsize); + bin = (char *) realloc(bin, bufsize); p = bin + blen; } while (!gzeof(zf)); gzclose(zf); @@ -411,37 +399,37 @@ void futurerestore::loadAPTickets(const vector &apticketPaths){ } free(bin); } - + if (_isUpdateInstall) { - if(plist_t update = plist_dict_get_item(apticket, "updateInstall")){ + if (plist_t update = plist_dict_get_item(apticket, "updateInstall")) { plist_t cpy = plist_copy(update); - plist_t gen_cpy = NULL; - if(plist_t gen = plist_dict_get_item(apticket, "generator")) { - plist_t gen_cpy = plist_copy(gen); + plist_t gen_cpy = nullptr; + if (plist_t gen = plist_dict_get_item(apticket, "generator")) { + gen_cpy = plist_copy(gen); plist_free(gen); - plist_dict_insert_item(cpy, "generator", gen_cpy); + plist_dict_set_item(cpy, "generator", gen_cpy); } - if(gen_cpy != NULL) plist_free(gen_cpy); + if (gen_cpy != nullptr) plist_free(gen_cpy); plist_free(apticket); apticket = cpy; } } - + plist_t ticket = plist_dict_get_item(apticket, (_client->image4supported) ? "ApImg4Ticket" : "APTicket"); - uint64_t im4msize=0; + uint64_t im4msize = 0; plist_get_data_val(ticket, &im4m, &im4msize); - - retassure(im4msize, "Error: failed to load signing ticket file %s\n",apticketPath); - - _im4ms.push_back({im4m,im4msize}); + + retassure(im4msize, "Error: failed to load signing ticket file %s\n", apticketPath); + + _im4ms.emplace_back(im4m, im4msize); _aptickets.push_back(apticket); - printf("reading signing ticket %s is done\n",apticketPath); + printf("reading signing ticket %s is done\n", apticketPath); } } -uint64_t futurerestore::getBasebandGoldCertIDFromDevice(){ - if (!_client->preflight_info){ - if (normal_get_preflight_info(_client, &_client->preflight_info) == -1){ +uint64_t futurerestore::getBasebandGoldCertIDFromDevice() { + if (!_client->preflight_info) { + if (normal_get_preflight_info(_client, &_client->preflight_info) == -1) { printf("[WARNING] failed to read BasebandGoldCertID from device! Is it already in recovery?\n"); return 0; } @@ -457,9 +445,9 @@ uint64_t futurerestore::getBasebandGoldCertIDFromDevice(){ return val; } -char *futurerestore::getiBootBuild(){ - if (!_ibootBuild){ - if (_client->recovery == NULL) { +char *futurerestore::getiBootBuild() { + if (!_ibootBuild) { + if (_client->recovery == nullptr) { retassure(!recovery_client_new(_client), "Error: can't create new recovery client"); } irecv_getenv(_client->recovery->client, "build-version", &_ibootBuild); @@ -468,48 +456,53 @@ char *futurerestore::getiBootBuild(){ return _ibootBuild; } -pair, size_t> getIPSWComponent(struct idevicerestore_client_t* client, plist_t build_identity, string component){ +pair, size_t> +getIPSWComponent(struct idevicerestore_client_t *client, plist_t build_identity, const string &component) { ptr_smart path; - unsigned char* component_data = NULL; + unsigned char *component_data = nullptr; unsigned int component_size = 0; - if (!(char*)path) { - retassure(!build_identity_get_component_path(build_identity, component.c_str(), &path),"ERROR: Unable to get path for component '%s'\n", component.c_str()); + if (!(char *) path) { + retassure(!build_identity_get_component_path(build_identity, component.c_str(), &path), + "ERROR: Unable to get path for component '%s'\n", component.c_str()); } - - retassure(!extract_component(client->ipsw, (char*)path, &component_data, &component_size),"ERROR: Unable to extract component: %s\n", component.c_str()); - - return {(char*)component_data,component_size}; + + retassure(!extract_component(client->ipsw, (char *) path, &component_data, &component_size), + "ERROR: Unable to extract component: %s\n", component.c_str()); + + return {(char *) component_data, component_size}; } -void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootargs){ +void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootargs) { #ifndef HAVE_LIBIPATCHER reterror("compiled without libipatcher"); #else - idevicerestore_mode_t *mode = 0; - libipatcher::fw_key iBSSKeys; - libipatcher::fw_key iBECKeys; - pair, size_t> iBSS; - pair, size_t> iBEC; - FILE *ibss = NULL; - FILE *ibec = NULL; + idevicerestore_mode_t *mode = nullptr; + libipatcher::fw_key iBSSKeys{}; + libipatcher::fw_key iBECKeys{}; + pair, size_t> iBSS; + pair, size_t> iBEC; + FILE *ibss = nullptr; + FILE *ibec = nullptr; int rv; bool cache1 = false; bool cache2 = false; - std::string img3_end = ".patched.img3"; - std::string img4_end = ".patched.img4"; - std::string ibss_name = FUTURERESTORE_TMP_PATH"/ibss."; - std::string ibec_name = FUTURERESTORE_TMP_PATH"/ibec."; + std::string img3_end(".patched.img3"); + std::string img4_end(".patched.img4"); + std::string ibss_name(futurerestoreTempPath + "/ibss."); + std::string ibec_name(futurerestoreTempPath + "/ibec."); /* Assure device is in dfu */ irecv_device_event_subscribe(&_client->irecv_e_ctx, irecv_event_cb, _client); idevice_event_subscribe(idevice_event_cb, _client); - _client->idevice_e_ctx = (void *)idevice_event_cb; + _client->idevice_e_ctx = (void *) idevice_event_cb; getDeviceMode(true); mutex_lock(&_client->device_event_mutex); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 1000); - retassure(((_client->mode == MODE_DFU) || (mutex_unlock(&_client->device_event_mutex),0)), "Device isn't in DFU mode!"); - retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in DFU Mode!"); + retassure(((_client->mode == MODE_DFU) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device isn't in DFU mode!"); + retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in DFU Mode!"); mutex_unlock(&_client->device_event_mutex); info("Device found in DFU Mode.\n"); @@ -519,20 +512,20 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg ibec_name.append("."); ibss_name.append(_client->build); ibec_name.append(_client->build); - if(_client->image4supported) { + if (_client->image4supported) { ibss_name.append(img4_end); ibec_name.append(img4_end); } else { ibss_name.append(img3_end); ibec_name.append(img3_end); } - if(!_noCache) { + if (!_noCache) { ibss = fopen(ibss_name.c_str(), "rb"); if (ibss) { fseek(ibss, 0, SEEK_END); iBSS.second = ftell(ibss); fseek(ibss, 0, SEEK_SET); - retassure(iBSS.first = (char *) malloc(iBSS.second), "failed to malloc memory for Rose\n"); + retassure(iBSS.first = (char *) malloc(iBSS.second), "failed to calloc memory for Rose\n"); size_t freadRet = 0; retassure((freadRet = fread((char *) iBSS.first, 1, iBSS.second, ibss)) == iBSS.second, "failed to load iBSS. size=%zu but fread returned %zu\n", iBSS.second, freadRet); @@ -544,7 +537,7 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg fseek(ibec, 0, SEEK_END); iBEC.second = ftell(ibec); fseek(ibec, 0, SEEK_SET); - retassure(iBEC.first = (char *) malloc(iBEC.second), "failed to malloc memory for Rose\n"); + retassure(iBEC.first = (char *) malloc(iBEC.second), "failed to calloc memory for Rose\n"); size_t freadRet = 0; retassure((freadRet = fread((char *) iBEC.first, 1, iBEC.second, ibec)) == iBEC.second, "failed to load iBEC. size=%zu but fread returned %zu\n", iBEC.second, freadRet); @@ -554,55 +547,58 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg } /* Patch bootloaders */ - if(!cache1 && !cache2) { + if (!cache1 && !cache2) { try { std::string board = getDeviceBoardNoCopy(); info("Getting firmware keys for: %s\n", board.c_str()); - if(board == "n71ap" || board == "n71map" || board == "n69ap" || board == "n69uap" || board == "n66ap" || board == "n66map") { - if(!_noIBSS && !cache1) { - iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS", board); + if (board == "n71ap" || board == "n71map" || board == "n69ap" || board == "n69uap" || board == "n66ap" || + board == "n66map") { + if (!_noIBSS && !cache1) { + iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS", + board); } - if(!cache2) { - iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC", board); + if (!cache2) { + iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC", + board); } } else { - if(!_noIBSS && !cache1) { + if (!_noIBSS && !cache1) { iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS"); } - if(!cache2) { + if (!cache2) { iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC"); } } } catch (tihmstar::exception &e) { - reterror("getting keys failed with error: %d (%s). Are keys publicly available?",e.code(),e.what()); + reterror("getting keys failed with error: %d (%s). Are keys publicly available?", e.code(), e.what()); } } - if(!iBSS.first && !_noIBSS){ + if (!iBSS.first && !_noIBSS) { info("Patching iBSS\n"); iBSS = getIPSWComponent(_client, build_identity, "iBSS"); - iBSS = move(libipatcher::patchiBSS((char*)iBSS.first, iBSS.second, iBSSKeys)); + iBSS = move(libipatcher::patchiBSS((char *) iBSS.first, iBSS.second, iBSSKeys)); } - if(!iBEC.first) { + if (!iBEC.first) { info("Patching iBEC\n"); iBEC = getIPSWComponent(_client, build_identity, "iBEC"); - iBEC = move(libipatcher::patchiBEC((char*)iBEC.first, iBEC.second, iBECKeys, std::move(bootargs))); + iBEC = move(libipatcher::patchiBEC((char *) iBEC.first, iBEC.second, iBECKeys, std::move(bootargs))); } if (_client->image4supported) { /* if this is 64-bit, we need to back IM4P to IMG4 also due to the nature of iBoot64Patchers sigpatches we need to stich a valid signed im4m to it (but nonce is ignored) */ - if(!cache1 && !_noIBSS) { + if (!cache1 && !_noIBSS) { info("Repacking patched iBSS as IMG4\n"); iBSS = move(libipatcher::packIM4PToIMG4(iBSS.first, iBSS.second, _im4ms[0].first, _im4ms[0].second)); } - if(!cache2) { + if (!cache2) { info("Repacking patched iBEC as IMG4\n"); iBEC = move(libipatcher::packIM4PToIMG4(iBEC.first, iBEC.second, _im4ms[0].first, _im4ms[0].second)); } } - if(!_noIBSS) { + if (!_noIBSS) { retassure(ibss = fopen(ibss_name.c_str(), "wb"), "can't save patched ibss at %s\n", ibss_name.c_str()); retassure(rv = fwrite(iBSS.first, iBSS.second, 1, ibss), "can't save patched ibss at %s\n", ibss_name.c_str()); fflush(ibss); @@ -615,7 +611,7 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg /* Send and boot bootloaders */ irecv_error_t err = IRECV_E_UNKNOWN_ERROR; - if(!_noIBSS) { + if (!_noIBSS) { /* send iBSS */ info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second); mutex_lock(&_client->device_event_mutex); @@ -625,146 +621,179 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg info("Booting iBSS, waiting for device to disconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - - retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); - info("Booting iBSS, waiting for device to reconnect...\n"); + + retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); + info("Booting iBSS, waiting for device to reconnect...\n"); } bool dfu = false; - if((_client->device->chip_id >= 0x7000 && _client->device->chip_id <= 0x8004) || (_client->device->chip_id >= 0x8900 && _client->device->chip_id <= 0x8965)) { + if ((_client->device->chip_id >= 0x7000 && _client->device->chip_id <= 0x8004) || + (_client->device->chip_id >= 0x8900 && _client->device->chip_id <= 0x8965)) { cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((_client->mode == MODE_DFU) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBSS. Reset device and try again"); + retassure(((_client->mode == MODE_DFU) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not reconnect. Possibly invalid iBSS. Reset device and try again"); if (_client->build_major > 8) { mutex_unlock(&_client->device_event_mutex); getDeviceMode(true); - retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in DFU Mode!"); + retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in DFU Mode!"); retassure(irecv_usb_set_configuration(_client->dfu->client, 1) >= 0, "ERROR: set configuration failed\n"); /* send iBEC */ info("Sending %s (%lu bytes)...\n", "iBEC", iBEC.second); mutex_lock(&_client->device_event_mutex); - err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBEC.first, (unsigned long)iBEC.second, 1); - retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err)); + err = irecv_send_buffer(_client->dfu->client, (unsigned char *) (char *) iBEC.first, + (unsigned long) iBEC.second, 1); + retassure(err == IRECV_E_SUCCESS, "ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err)); info("Booting iBEC, waiting for device to disconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); + retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); info("Booting iBEC, waiting for device to reconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((_client->mode == MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); + retassure(((_client->mode == MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&_client->device_event_mutex); getDeviceMode(true); - retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode!"); + retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || + (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in Recovery Mode!"); } - } else if((_client->device->chip_id >= 0x8006 && _client->device->chip_id <= 0x8030) || (_client->device->chip_id >= 0x8101 && _client->device->chip_id <= 0x8301)) { + } else if ((_client->device->chip_id >= 0x8006 && _client->device->chip_id <= 0x8030) || + (_client->device->chip_id >= 0x8101 && _client->device->chip_id <= 0x8301)) { dfu = true; cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((_client->mode == MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBSS. Reset device and try again"); + retassure(((_client->mode == MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not reconnect. Possibly invalid iBSS. Reset device and try again"); } else { mutex_unlock(&_client->device_event_mutex); reterror("Device not supported!\n"); } /* Verify correct nonce/set nonce */ - if(_client->image4supported) { - char *deviceGen = NULL; - cleanup([&]{ + if (_client->image4supported) { + char *deviceGen = nullptr; + cleanup([&] { safeFree(deviceGen); }); mutex_unlock(&_client->device_event_mutex); - if(_client->device->chip_id < 0x8015) { - if(dfu) { + if (_client->device->chip_id < 0x8015) { + if (dfu) { assure(!irecv_send_command(_client->dfu->client, "bgcolor 255 0 0")); } else { assure(!irecv_send_command(_client->recovery->client, "bgcolor 255 0 0")); } sleep(2); } - auto nonceelem = img4tool::getValFromIM4M({_im4ms[0].first,_im4ms[0].second}, 'BNCH'); + auto nonceelem = img4tool::getValFromIM4M({_im4ms[0].first, _im4ms[0].second}, 'BNCH'); info("ApNonce pre-hax:\n"); - if(get_ap_nonce(_client, &_client->nonce, &_client->nonce_size) < 0) { + if (get_ap_nonce(_client, &_client->nonce, &_client->nonce_size) < 0) { reterror("Failed to get apnonce from device!"); } - std::string generator = (_setNonce && _custom_nonce != NULL) ? _custom_nonce : getGeneratorFromSHSH2(_client->tss); + std::string generator = (_setNonce && _custom_nonce != nullptr) ? _custom_nonce : getGeneratorFromSHSH2( + _client->tss); - if((_setNonce && _custom_nonce != NULL) || memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) != 0) { - if(!_setNonce) + if ((_setNonce && _custom_nonce != nullptr) || + memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) != 0) { + if (!_setNonce) info("ApNonce from device doesn't match IM4M nonce, applying hax...\n"); assure(_client->tss); info("Writing generator=%s to nvram!\n", generator.c_str()); - retassure(!irecv_setenv(_client->recovery->client, "com.apple.System.boot-nonce", generator.c_str()), "Failed to write generator to nvram!"); + retassure(!irecv_setenv(_client->recovery->client, "com.apple.System.boot-nonce", generator.c_str()), + "Failed to write generator to nvram!"); retassure(!irecv_saveenv(_client->recovery->client), "Failed to save nvram!"); getDeviceMode(true); - retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode!"); + retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in Recovery Mode!"); retassure(irecv_usb_set_configuration(_client->dfu->client, 1) >= 0, "ERROR: set configuration failed\n"); /* send iBEC */ info("Sending %s (%lu bytes)...\n", "iBEC", iBEC.second); mutex_lock(&_client->device_event_mutex); - err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBEC.first, (unsigned long)iBEC.second, 1); - retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err)); - retassure(((irecv_send_command(_client->dfu->client, "go") == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect/reconnect. Possibly invalid iBEC. Reset device and try again\n"); + err = irecv_send_buffer(_client->dfu->client, (unsigned char *) (char *) iBEC.first, + (unsigned long) iBEC.second, 1); + retassure(err == IRECV_E_SUCCESS, "ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err)); + retassure(((irecv_send_command(_client->dfu->client, "go") == IRECV_E_SUCCESS) || + (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not disconnect/reconnect. Possibly invalid iBEC. Reset device and try again\n"); info("Booting iBEC, waiting for device to disconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); + retassure(((_client->mode == MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); info("Booting iBEC, waiting for device to reconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((_client->mode == MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); + retassure(((_client->mode == MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&_client->device_event_mutex); getDeviceMode(true); - retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode after ApNonce hax!"); + retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || + (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in Recovery Mode after ApNonce hax!"); printf("APnonce post-hax:\n"); - if(get_ap_nonce(_client, &_client->nonce, &_client->nonce_size) < 0) { + if (get_ap_nonce(_client, &_client->nonce, &_client->nonce_size) < 0) { reterror("Failed to get apnonce from device!"); } assure(!irecv_send_command(_client->recovery->client, "bgcolor 255 255 0")); - retassure(_setNonce || memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) == 0, "ApNonce from device doesn't match IM4M nonce after applying ApNonce hax. Aborting!"); + retassure(_setNonce || memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) == 0, + "ApNonce from device doesn't match IM4M nonce after applying ApNonce hax. Aborting!"); } else { getDeviceMode(true); - retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode!"); + retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in Recovery Mode!"); retassure(irecv_usb_set_configuration(_client->dfu->client, 1) >= 0, "ERROR: set configuration failed\n"); /* send iBEC */ info("Sending %s (%lu bytes)...\n", "iBEC", iBEC.second); mutex_lock(&_client->device_event_mutex); - err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBEC.first, (unsigned long)iBEC.second, 1); - retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err)); - retassure(((irecv_send_command(_client->dfu->client, "go") == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect/reconnect. Possibly invalid iBEC. Reset device and try again\n"); + err = irecv_send_buffer(_client->dfu->client, (unsigned char *) (char *) iBEC.first, + (unsigned long) iBEC.second, 1); + retassure(err == IRECV_E_SUCCESS, "ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err)); + retassure(((irecv_send_command(_client->dfu->client, "go") == IRECV_E_SUCCESS) || + (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not disconnect/reconnect. Possibly invalid iBEC. Reset device and try again\n"); info("Booting iBEC, waiting for device to disconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); + retassure(((MODE_UNKNOWN) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); info("Booting iBEC, waiting for device to reconnect...\n"); cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000); - retassure(((MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); + retassure(((MODE_RECOVERY) || (mutex_unlock(&_client->device_event_mutex), 0)), + "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&_client->device_event_mutex); getDeviceMode(true); - retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode after ApNonce hax!"); + retassure(((recovery_client_new(_client) == IRECV_E_SUCCESS) || + (mutex_unlock(&_client->device_event_mutex), 0)), + "Failed to connect to device in Recovery Mode after ApNonce hax!"); assure(!irecv_send_command(_client->recovery->client, "bgcolor 255 255 0")); info("APNonce from device already matches IM4M nonce, no need for extra hax...\n"); } - retassure(!irecv_setenv(_client->recovery->client, "com.apple.System.boot-nonce", generator.c_str()), "failed to write generator to nvram"); + retassure(!irecv_setenv(_client->recovery->client, "com.apple.System.boot-nonce", generator.c_str()), + "failed to write generator to nvram"); retassure(!irecv_saveenv(_client->recovery->client), "failed to save nvram"); uint64_t gen = std::stoul(generator, nullptr, 16); - uint8_t *nonce = (uint8_t *)calloc(_client->nonce_size, sizeof(uint8_t)); - if(_client->nonce_size == 20) { - SHA1((unsigned char *)&gen, 8, nonce); - } else if(_client->nonce_size == 32) { - SHA384((unsigned char *)&gen, 8, nonce); + auto *nonce = (uint8_t *) calloc(_client->nonce_size, sizeof(uint8_t)); + if (_client->nonce_size == 20) { + SHA1((unsigned char *) &gen, 8, nonce); + } else if (_client->nonce_size == 32) { + SHA384((unsigned char *) &gen, 8, nonce); } else { - reterror("Failed to set nonce generator: %s! Unknown nonce size: %d\n", generator.c_str(), _client->nonce_size); + reterror("Failed to set nonce generator: %s! Unknown nonce size: %d\n", generator.c_str(), + _client->nonce_size); } - for(int i = 0; i < _client->nonce_size; i++) { - if(*(uint8_t *)(nonce + i) != *(uint8_t *)(_client->nonce + i)) { + for (int i = 0; i < _client->nonce_size; i++) { + if (*(uint8_t *) (nonce + i) != *(uint8_t *) (_client->nonce + i)) { reterror("Failed to set nonce generator: %s!\n", generator.c_str()); } } info("Successfully set nonce generator: %s\n", generator.c_str()); - if(_setNonce) { + if (_setNonce) { info("Done setting nonce!\n"); info("Use futurerestore --exit-recovery to go back to normal mode if you aren't restoring.\n"); setAutoboot(false); @@ -778,77 +807,83 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg #endif //HAVE_LIBIPATCHER } -void get_custom_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component, unsigned char** data, unsigned int *size){ +void get_custom_component(struct idevicerestore_client_t *client, plist_t build_identity, const char *component, + unsigned char **data, unsigned int *size) { #ifndef HAVE_LIBIPATCHER reterror("compiled without libipatcher"); #else try { auto comp = getIPSWComponent(client, build_identity, component); - comp = move(libipatcher::decryptFile3((char*)comp.first, comp.second, libipatcher::getFirmwareKey(client->device->product_type, client->build, component))); - *data = (unsigned char*)(char*)comp.first; + comp = move(libipatcher::decryptFile3((char *) comp.first, comp.second, + libipatcher::getFirmwareKey(client->device->product_type, client->build, + component))); + *data = (unsigned char *) (char *) comp.first; *size = comp.second; comp.first = NULL; //don't free on destruction } catch (tihmstar::exception &e) { - reterror("ERROR: libipatcher failed with reason %d (%s)\n",e.code(),e.what()); + reterror("ERROR: libipatcher failed with reason %d (%s)\n", e.code(), e.what()); } - + #endif } -void futurerestore::doRestore(const char *ipsw){ - plist_t buildmanifest = NULL; +void futurerestore::doRestore(const char *ipsw) { + plist_t buildmanifest = nullptr; int delete_fs = 0; - char* filesystem = NULL; - cleanup([&]{ + char *filesystem = nullptr; + cleanup([&] { info("Cleaning up...\n"); safeFreeCustom(buildmanifest, plist_free); if (delete_fs && filesystem) unlink(filesystem); }); - struct idevicerestore_client_t* client = _client; - plist_t build_identity = NULL; + struct idevicerestore_client_t *client = _client; + plist_t build_identity = nullptr; client->ipsw = strdup(ipsw); if (_noRestore) client->flags |= FLAG_NO_RESTORE; if (!_isUpdateInstall) client->flags |= FLAG_ERASE; - + irecv_device_event_subscribe(&client->irecv_e_ctx, irecv_event_cb, client); idevice_event_subscribe(idevice_event_cb, client); - client->idevice_e_ctx = (void*)idevice_event_cb; + client->idevice_e_ctx = (void *) idevice_event_cb; mutex_lock(&client->device_event_mutex); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - - retassure(client->mode != MODE_UNKNOWN, "Unable to discover device mode. Please make sure a device is attached.\n"); + + retassure(client->mode != MODE_UNKNOWN, "Unable to discover device mode. Please make sure a device is attached.\n"); if (client->mode != MODE_RECOVERY) { retassure(client->mode == MODE_DFU, "Device is in unexpected mode detected!"); retassure(_enterPwnRecoveryRequested, "Device is in DFU mode detected, but we were expecting recovery mode!"); - }else{ + } else { retassure(!_enterPwnRecoveryRequested, "--use-pwndfu was specified, but device found in recovery mode!"); } - + info("Found device in %s mode\n", client->mode->string); mutex_unlock(&client->device_event_mutex); info("Identified device as %s, %s\n", getDeviceBoardNoCopy(), getDeviceModelNoCopy()); - retassure(!access(client->ipsw, F_OK),"ERROR: Firmware file %s does not exist.\n", client->ipsw); // verify if ipsw file exists + retassure(!access(client->ipsw, F_OK), "ERROR: Firmware file %s does not exist.\n", + client->ipsw); // verify if ipsw file exists info("Extracting BuildManifest from iPSW\n"); { int unused; - retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused),"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw); + retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused), + "ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw); } /* check if device type is supported by the given build manifest */ - retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type),"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n"); - + retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type), + "ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n"); + /* print iOS information from the manifest */ build_manifest_get_version_information(buildmanifest, 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 (_enterPwnRecoveryRequested) //we are in pwnDFU, so we don't need to check nonces client->tss = _aptickets.at(0); else if (!(client->tss = nonceMatchesApTickets())) @@ -859,16 +894,24 @@ void futurerestore::doRestore(const char *ipsw){ if (_enterPwnRecoveryRequested && _client->image4supported) { - retassure(plist_dict_get_item(_client->tss, "generator"), "signing ticket file does not contain generator. But a generator is required for 64-bit pwnDFU restore"); + retassure(plist_dict_get_item(_client->tss, "generator"), + "signing ticket file does not contain generator. But a generator is required for 64-bit pwnDFU restore"); } - - retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, _isUpdateInstall),"ERROR: Unable to find any build identities for iPSW\n"); + + retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, + _isUpdateInstall), + "ERROR: Unable to find any build identities for iPSW\n"); if (_client->image4supported) { - if (!(client->sepBuildIdentity = getBuildidentityWithBoardconfig(_sepbuildmanifest, client->device->hardware_model, _isUpdateInstall))){ + if (!(client->sepBuildIdentity = getBuildidentityWithBoardconfig(_sepbuildmanifest, + client->device->hardware_model, + _isUpdateInstall))) { retassure(_isPwnDfu, "ERROR: Unable to find any build identities for SEP\n"); - warning("can't find buildidentity for SEP with InstallType=%s. However pwnDFU was requested, so trying fallback to %s",(_isUpdateInstall ? "UPDATE" : "ERASE"),(!_isUpdateInstall ? "UPDATE" : "ERASE")); - retassure((client->sepBuildIdentity = getBuildidentityWithBoardconfig(_sepbuildmanifest, client->device->hardware_model, !_isUpdateInstall)), + warning("can't find buildidentity for SEP with InstallType=%s. However pwnDFU was requested, so trying fallback to %s", + (_isUpdateInstall ? "UPDATE" : "ERASE"), (!_isUpdateInstall ? "UPDATE" : "ERASE")); + retassure((client->sepBuildIdentity = getBuildidentityWithBoardconfig(_sepbuildmanifest, + client->device->hardware_model, + !_isUpdateInstall)), "ERROR: Unable to find any build identities for SEP\n"); } } @@ -881,9 +924,9 @@ void futurerestore::doRestore(const char *ipsw){ uint64_t deviceEcid = getDeviceEcid(); uint64_t im4mEcid = 0; if (_client->image4supported) { - auto ecid = img4tool::getValFromIM4M({im4m.first,im4m.second}, 'ECID'); + auto ecid = img4tool::getValFromIM4M({im4m.first, im4m.second}, 'ECID'); im4mEcid = ecid.getIntegerValue(); - }else{ + } else { im4mEcid = getEcidFromSCAB(im4m.first, im4m.second); } @@ -891,34 +934,33 @@ void futurerestore::doRestore(const char *ipsw){ if (im4mEcid != deviceEcid) { error("ECID inside APTicket does not match device ECID\n"); - printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n",im4mEcid,deviceEcid); - if(_skipBlob) { + printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n", im4mEcid, deviceEcid); + if (_skipBlob) { info("[WARNING] NOT VALIDATING SHSH BLOBS ECID!\n"); } else { reterror("APTicket can't be used for restoring this device\n"); } - }else + } else printf("Verified ECID in APTicket matches device ECID\n"); if (_client->image4supported) { printf("checking APTicket to be valid for this restore...\n"); - uint64_t deviceEcid = getDeviceEcid(); if (im4mEcid != deviceEcid) { error("ECID inside APTicket does not match device ECID\n"); - printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n",im4mEcid,deviceEcid); - if(_skipBlob) { + printf("APTicket is valid for %16llu (dec) but device is %16llu (dec)\n", im4mEcid, deviceEcid); + if (_skipBlob) { info("[WARNING] NOT VALIDATING SHSH BLOBS ECID!\n"); } else { reterror("APTicket can't be used for restoring this device\n"); } - }else + } else printf("Verified ECID in APTicket matches device ECID\n"); - plist_t ticketIdentity = NULL; - + plist_t ticketIdentity = nullptr; + try { - ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first,im4m.second}, buildmanifest); + ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first, im4m.second}, buildmanifest); } catch (tihmstar::exception &e) { if (_skipBlob) { info("[WARNING] NOT VALIDATING SHSH BLOBS IM4M!\n"); @@ -926,40 +968,41 @@ void futurerestore::doRestore(const char *ipsw){ return; } } - + if (!_skipBlob && !ticketIdentity) { printf("Failed to get exact match for build identity, using fallback to ignore certain values\n"); - ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first,im4m.second}, buildmanifest, {"RestoreRamDisk","RestoreTrustCache"}); + ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first, im4m.second}, buildmanifest, + {"RestoreRamDisk", "RestoreTrustCache"}); } /* TODO: make this nicer! for now a simple pointercompare should be fine, because both plist_t should point into the same buildidentity inside the buildmanifest */ - if (ticketIdentity != build_identity ){ + if (ticketIdentity != build_identity) { error("BuildIdentity selected for restore does not match APTicket\n\n"); info("BuildIdentity selected for restore:\n"); img4tool::printGeneralBuildIdentityInformation(build_identity); info("\nBuildIdentity is valid for the APTicket:\n"); - if (ticketIdentity) img4tool::printGeneralBuildIdentityInformation(ticketIdentity),putchar('\n'); - else{ + if (ticketIdentity) img4tool::printGeneralBuildIdentityInformation(ticketIdentity), putchar('\n'); + else { info("IM4M is not valid for any restore within the Buildmanifest\n"); info("This APTicket can't be used for restoring this firmware\n"); } - if(_skipBlob) { + if (_skipBlob) { info("[WARNING] NOT VALIDATING SHSH BLOBS!\n"); } else { reterror("APTicket can't be used for this restore\n"); } - }else{ - if (!img4tool::isIM4MSignatureValid({im4m.first,im4m.second})){ + } else { + if (!img4tool::isIM4MSignatureValid({im4m.first, im4m.second})) { info("IM4M signature is not valid!\n"); } info("Verified APTicket to be valid for this restore\n"); } - }else if (_enterPwnRecoveryRequested){ + } else if (_enterPwnRecoveryRequested) { info("[WARNING] skipping ramdisk hash check, since device is in pwnDFU according to user\n"); - }else{ + } else { info("[WARNING] full buildidentity check is not implemented, only comparing ramdisk hash.\n"); auto ticket = getRamdiskHashFromSCAB(im4m.first, im4m.second); @@ -967,37 +1010,43 @@ void futurerestore::doRestore(const char *ipsw){ size_t tickethashSize = ticket.second; uint64_t manifestDigestSize = 0; - char *manifestDigest = NULL; + char *manifestDigest = nullptr; plist_t restoreRamdisk = plist_dict_get_item(manifest, "RestoreRamDisk"); plist_t digest = plist_dict_get_item(restoreRamdisk, "Digest"); plist_get_data_val(digest, &manifestDigest, &manifestDigestSize); - if (tickethashSize == manifestDigestSize && memcmp(tickethash, manifestDigest, tickethashSize) == 0){ + if (tickethashSize == manifestDigestSize && memcmp(tickethash, manifestDigest, tickethashSize) == 0) { printf("Verified APTicket to be valid for this restore\n"); free(manifestDigest); - }else{ + } else { free(manifestDigest); printf("APTicket ramdisk hash does not match the ramdisk we are trying to boot. Are you using correct install type (Update/Erase)?\n"); reterror("APTicket can't be used for this restore\n"); } } - if (_basebandbuildmanifest){ - if (!(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, client->device->hardware_model, _isUpdateInstall))){ - retassure(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, client->device->hardware_model, !_isUpdateInstall), "ERROR: Unable to find any build identities for Baseband\n"); - info("[WARNING] Unable to find Baseband buildidentities for restore type %s, using fallback %s\n", (_isUpdateInstall) ? "Update" : "Erase",(!_isUpdateInstall) ? "Update" : "Erase"); + if (_basebandbuildmanifest) { + if (!(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, + client->device->hardware_model, + _isUpdateInstall))) { + retassure(client->basebandBuildIdentity = getBuildidentityWithBoardconfig(_basebandbuildmanifest, + client->device->hardware_model, + !_isUpdateInstall), + "ERROR: Unable to find any build identities for Baseband\n"); + info("[WARNING] Unable to find Baseband buildidentities for restore type %s, using fallback %s\n", + (_isUpdateInstall) ? "Update" : "Erase", (!_isUpdateInstall) ? "Update" : "Erase"); } - client->bbfwtmp = (char*)_basebandPath; + client->bbfwtmp = (char *)basebandTempPath.c_str(); plist_t bb_manifest = plist_dict_get_item(client->basebandBuildIdentity, "Manifest"); plist_t bb_baseband = plist_copy(plist_dict_get_item(bb_manifest, "BasebandFirmware")); plist_dict_set_item(manifest, "BasebandFirmware", bb_baseband); retassure(_client->basebandBuildIdentity, "BasebandBuildIdentity not loaded, refusing to continue"); - }else{ + } else { warning("WARNING: we don't have a basebandbuildmanifest, does not flashing baseband!\n"); } @@ -1007,7 +1056,7 @@ void futurerestore::doRestore(const char *ipsw){ plist_t sep_sep = plist_copy(plist_dict_get_item(sep_manifest, "SEP")); plist_dict_set_item(manifest, "SEP", sep_sep); unsigned char genHash[48]; //SHA384 digest length - ptr_smartsephash = NULL; + ptr_smart sephash = NULL; uint64_t sephashlen = 0; plist_t digest = plist_dict_get_item(sep_sep, "Digest"); @@ -1016,46 +1065,57 @@ void futurerestore::doRestore(const char *ipsw){ plist_get_data_val(digest, reinterpret_cast(&sephash), &sephashlen); if (sephashlen == 20) - SHA1((unsigned char*)_client->sepfwdata, (unsigned int)_client->sepfwdatasize, genHash); + SHA1((unsigned char *) _client->sepfwdata, (unsigned int) _client->sepfwdatasize, genHash); else - SHA384((unsigned char*)_client->sepfwdata, (unsigned int)_client->sepfwdatasize, genHash); + SHA384((unsigned char *) _client->sepfwdata, (unsigned int) _client->sepfwdatasize, genHash); retassure(!memcmp(genHash, sephash, sephashlen), "ERROR: SEP does not match sepmanifest\n"); } build_identity_print_information(build_identity); // print information about current build identity //check for enterpwnrecovery, because we could be in DFU mode - if (_enterPwnRecoveryRequested){ - retassure((getDeviceMode(true) == _MODE_DFU) || (getDeviceMode(false) == _MODE_RECOVERY && _noIBSS), "unexpected device mode\n"); - irecv_device_event_unsubscribe(client->irecv_e_ctx); - client->idevice_e_ctx = NULL; - std::string bootargs = ""; - if(_boot_args != NULL) { + if (_enterPwnRecoveryRequested) { + retassure((getDeviceMode(true) == _MODE_DFU) || (getDeviceMode(false) == _MODE_RECOVERY && _noIBSS), + "unexpected device mode\n"); + if(client->irecv_e_ctx) { + irecv_device_event_unsubscribe(client->irecv_e_ctx); + } + if(client->idevice_e_ctx != nullptr) { + client->idevice_e_ctx = nullptr; + } + std::string bootargs; + if (_boot_args != nullptr) { bootargs = _boot_args; } else { if (_serial) { bootargs.append("serial=0x3 "); } bootargs.append("rd=md0 "); - if(!_isUpdateInstall) { + if (!_isUpdateInstall) { bootargs.append("nand-enable-reformat=0x1 "); } - bootargs.append("-v -restore debug=0x2014e keepsyms=0x1 amfi=0xff amfi_allow_any_signature=0x1 amfi_get_out_of_my_way=0x1 cs_enforcement_disable=0x1"); + bootargs.append( + "-v -restore debug=0x2014e keepsyms=0x1 amfi=0xff amfi_allow_any_signature=0x1 amfi_get_out_of_my_way=0x1 cs_enforcement_disable=0x1"); } enterPwnRecovery(build_identity, bootargs); - irecv_device_event_unsubscribe(_client->irecv_e_ctx); - _client->idevice_e_ctx = NULL; + if(_client->irecv_e_ctx) { + irecv_device_event_unsubscribe(_client->irecv_e_ctx); + } + if(_client->idevice_e_ctx != nullptr) { + _client->idevice_e_ctx = nullptr; + } irecv_device_event_subscribe(&client->irecv_e_ctx, irecv_event_cb, _client); idevice_event_subscribe(idevice_event_cb, client); - client->idevice_e_ctx = (void *)idevice_event_cb; + client->idevice_e_ctx = (void *) idevice_event_cb; } - + // Get filesystem name from build identity - char* fsname = NULL; - retassure(!build_identity_get_component_path(build_identity, "OS", &fsname), "ERROR: Unable to get path for filesystem component\n"); + char *fsname = nullptr; + retassure(!build_identity_get_component_path(build_identity, "OS", &fsname), + "ERROR: Unable to get path for filesystem component\n"); // check if we already have an extracted filesystem - struct stat st; + struct stat st{}; memset(&st, '\0', sizeof(struct stat)); char tmpf[1024]; if (client->cache_dir) { @@ -1070,13 +1130,13 @@ void futurerestore::doRestore(const char *ipsw){ } else { strcpy(tmpf, client->ipsw); } - char* p = strrchr(tmpf, '.'); + char *p = strrchr(tmpf, '.'); if (p) { *p = '\0'; } if (stat(tmpf, &st) < 0) { - __mkdir(tmpf, 0755); + safe_mkdir(tmpf, 0755); } strcat(tmpf, "/"); strcat(tmpf, fsname); @@ -1084,7 +1144,7 @@ void futurerestore::doRestore(const char *ipsw){ memset(&st, '\0', sizeof(struct stat)); if (stat(tmpf, &st) == 0) { off_t fssize = 0; - ipsw_get_file_size(client->ipsw, fsname, (uint64_t*)&fssize); + ipsw_get_file_size(client->ipsw, fsname, (uint64_t *) &fssize); if ((fssize > 0) && (st.st_size == fssize)) { info("Using cached filesystem from '%s'\n", tmpf); filesystem = strdup(tmpf); @@ -1101,14 +1161,14 @@ void futurerestore::doRestore(const char *ipsw){ lock_info_t li; lock_file(lockfn, &li); - FILE* extf = NULL; + FILE *extf = nullptr; if (access(extfn, F_OK) != 0) { extf = fopen(extfn, "w"); } unlock_file(&li); if (!extf) { // use temp filename - filesystem = tempnam(NULL, "ipsw_"); + filesystem = reinterpret_cast(mkstemp(const_cast("ipsw_"))); if (!filesystem) { error("WARNING: Could not get temporary filename, using '%s' in current directory\n", fsname); filesystem = strdup(fsname); @@ -1122,7 +1182,8 @@ void futurerestore::doRestore(const char *ipsw){ remove(lockfn); info("Extracting filesystem from iPSW\n"); - retassure(!ipsw_extract_to_file_with_progress(client->ipsw, fsname, filesystem, 1),"ERROR: Unable to extract filesystem from iPSW\n"); + retassure(!ipsw_extract_to_file_with_progress(client->ipsw, fsname, filesystem, 1), + "ERROR: Unable to extract filesystem from iPSW\n"); // rename .extract to if (strstr(filesystem, ".extract")) { @@ -1137,48 +1198,52 @@ void futurerestore::doRestore(const char *ipsw){ mutex_lock(&_client->device_event_mutex); if (dfu_send_component(client, build_identity, "iBSS") < 0) { irecv_close(client->dfu->client); - client->dfu->client = NULL; + client->dfu->client = nullptr; reterror("ERROR: Unable to send iBSS to device\n"); } /* reconnect */ dfu_client_free(client); - + info("Booting iBSS, Waiting for device to disconnect...\n"); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - retassure((client->mode == MODE_UNKNOWN || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); + retassure((client->mode == MODE_UNKNOWN || (mutex_unlock(&client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); mutex_unlock(&client->device_event_mutex); info("Booting iBSS, Waiting for device to reconnect...\n"); mutex_lock(&_client->device_event_mutex); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - retassure((client->mode == MODE_DFU || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); + retassure((client->mode == MODE_DFU || (mutex_unlock(&client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBSS. Reset device and try again"); mutex_unlock(&client->device_event_mutex); - + dfu_client_new(client); /* send iBEC */ if (dfu_send_component(client, build_identity, "iBEC") < 0) { irecv_close(client->dfu->client); - client->dfu->client = NULL; + client->dfu->client = nullptr; reterror("ERROR: Unable to send iBEC to device\n"); } - + dfu_client_free(client); - + info("Booting iBEC, Waiting for device to disconnect...\n"); mutex_lock(&_client->device_event_mutex); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - retassure((client->mode == MODE_UNKNOWN || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); + retassure((client->mode == MODE_UNKNOWN || (mutex_unlock(&client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&client->device_event_mutex); info("Booting iBEC, Waiting for device to reconnect...\n"); mutex_lock(&_client->device_event_mutex); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - retassure((client->mode == MODE_RECOVERY || (mutex_unlock(&client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); + retassure((client->mode == MODE_RECOVERY || (mutex_unlock(&client->device_event_mutex), 0)), + "Device did not reconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&client->device_event_mutex); - }else{ + } else { if ((client->build_major > 8)) { if (!client->image4supported) { /* send APTicket */ @@ -1189,29 +1254,32 @@ void futurerestore::doRestore(const char *ipsw){ } } - if (_enterPwnRecoveryRequested){ + if (_enterPwnRecoveryRequested) { if (!_client->image4supported) { - if (strncmp(client->version, "10.", 3))//if pwnrecovery send all components decrypted, unless we're dealing with iOS 10 + if (strncmp(client->version, "10.", 3) == + 0)//if pwnrecovery send all components decrypted, unless we're dealing with iOS 10 client->recovery_custom_component_function = get_custom_component; } - }else if (!_rerestoreiOS9){ + } else if (!_rerestoreiOS9) { /* now we load the iBEC */ - retassure(!recovery_send_ibec(client, build_identity),"ERROR: Unable to send iBEC\n"); + retassure(!recovery_send_ibec(client, build_identity), "ERROR: Unable to send iBEC\n"); printf("waiting for device to reconnect... "); recovery_client_free(client); - + debug("Waiting for device to disconnect...\n"); mutex_unlock(&client->device_event_mutex); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - retassure((client->mode == MODE_UNKNOWN || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); + retassure((client->mode == MODE_UNKNOWN || (mutex_unlock(&client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&client->device_event_mutex); debug("Waiting for device to reconnect...\n"); mutex_unlock(&client->device_event_mutex); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000); - retassure((client->mode == MODE_RECOVERY || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); + retassure((client->mode == MODE_RECOVERY || (mutex_unlock(&client->device_event_mutex), 0)), + "Device did not disconnect. Possibly invalid iBEC. Reset device and try again"); mutex_unlock(&client->device_event_mutex); } @@ -1223,29 +1291,32 @@ void futurerestore::doRestore(const char *ipsw){ get_ecid(client, &client->ecid); if (client->mode == MODE_RECOVERY) { - retassure(client->srnm,"ERROR: could not retrieve device serial number. Can't continue.\n"); + retassure(client->srnm, "ERROR: could not retrieve device serial number. Can't continue.\n"); - if(client->device->chip_id < 0x8015) { - retassure(!irecv_send_command(client->recovery->client, "bgcolor 0 255 0"), "ERROR: Unable to set bgcolor\n"); + if (client->device->chip_id < 0x8015) { + retassure(!irecv_send_command(client->recovery->client, "bgcolor 0 255 0"), + "ERROR: Unable to set bgcolor\n"); info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n"); sleep(2); //show the user a green screen! } - retassure(!recovery_enter_restore(client, build_identity),"ERROR: Unable to place device into restore mode\n"); + retassure(!recovery_enter_restore(client, build_identity), "ERROR: Unable to place device into restore mode\n"); recovery_client_free(client); } if (_client->image4supported) { info("getting SEP ticket\n"); - retassure(!get_tss_response(client, client->sepBuildIdentity, &client->septss), "ERROR: Unable to get signing tickets for SEP\n"); + retassure(!get_tss_response(client, client->sepBuildIdentity, &client->septss), + "ERROR: Unable to get signing tickets for SEP\n"); retassure(_client->sepfwdatasize && _client->sepfwdata, "SEP is not loaded, refusing to continue"); } - + mutex_lock(&client->device_event_mutex); debug("Waiting for device to enter restore mode...\n"); cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 180000); - retassure((client->mode == MODE_RESTORE || (mutex_unlock(&client->device_event_mutex),0)), "Device can't enter to restore mode"); + retassure((client->mode == MODE_RESTORE || (mutex_unlock(&client->device_event_mutex), 0)), + "Device can't enter to restore mode"); mutex_unlock(&client->device_event_mutex); info("About to restore device... \n"); @@ -1254,538 +1325,478 @@ void futurerestore::doRestore(const char *ipsw){ else retassure(!(result), "ERROR: Unable to restore device\n"); } -int futurerestore::doJustBoot(const char *ipsw, string bootargs){ - reterror("not implemented"); -// int err = 0; -// //some memory might not get freed if this function throws an exception, but you probably don't want to catch that anyway. -// -// struct idevicerestore_client_t* client = _client; -// int unused; -// int result = 0; -// plist_t buildmanifest = NULL; -// plist_t build_identity = NULL; -// -// client->ipsw = strdup(ipsw); -// -// getDeviceMode(true); -// info("Found device in %s mode\n", client->mode->string); -// -// retassure((client->mode->index == MODE_DFU || client->mode->index == MODE_RECOVERY) && _enterPwnRecoveryRequested, "device not in DFU/Recovery mode\n"); -// -// // discover the device type -// retassure(check_hardware_model(client) && client->device,"ERROR: Unable to discover device model\n"); -// info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type); -// -// // verify if ipsw file exists -// retassure(!access(client->ipsw, F_OK), "ERROR: Firmware file %s does not exist.\n", client->ipsw); -// info("Extracting BuildManifest from IPSW\n"); -// -// retassure(!ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused),"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw); -// -// /* check if device type is supported by the given build manifest */ -// retassure(!build_manifest_check_compatibility(buildmanifest, client->device->product_type),"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n"); -// -// /* print iOS information from the manifest */ -// build_manifest_get_version_information(buildmanifest, 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"); -// -// retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, 0),"ERROR: Unable to find any build identities for IPSW\n"); -// -// /* print information about current build identity */ -// build_identity_print_information(build_identity); -// -// //check for enterpwnrecovery, because we could be in DFU mode -// retassure(_enterPwnRecoveryRequested, "enterPwnRecoveryRequested is not set, but required"); -// -// retassure(getDeviceMode(true) == MODE_DFU || getDeviceMode(false) == MODE_RECOVERY, "unexpected device mode\n"); -// -// enterPwnRecovery(build_identity, bootargs); -// -// client->recovery_custom_component_function = get_custom_component; -// -// for (int i=0;getDeviceMode(true) != MODE_RECOVERY && i<40; i++) putchar('.'),usleep(USEC_PER_SEC*0.5); -// putchar('\n'); -// -// retassure(check_mode(client), "failed to reconnect to device in recovery (iBEC) mode\n"); -// -// get_ecid(client, &client->ecid); -// -// client->flags |= FLAG_BOOT; -// -// if (client->mode->index == MODE_RECOVERY) { -// retassure(client->srnm,"ERROR: could not retrieve device serial number. Can't continue.\n"); -// -// retassure(!irecv_send_command(client->recovery->client, "bgcolor 0 255 0"), "ERROR: Unable to set bgcolor\n"); -// -// info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n"); -// sleep(2); //show the user a green screen! -// client->image4supported = true; //dirty hack to not require apticket -// -// retassure(!recovery_enter_restore(client, build_identity),"ERROR: Unable to place device into restore mode\n"); -// -// client->image4supported = false; -// recovery_client_free(client); -// } -// -// info("Cleaning up...\n"); -// -//error: -// safeFree(client->sepfwdata); -// safeFreeCustom(buildmanifest, plist_free); -// if (!result && !err) info("DONE\n"); -// return result ? abs(result) : err; -} - -futurerestore::~futurerestore(){ +futurerestore::~futurerestore() { recovery_client_free(_client); idevicerestore_client_free(_client); - for (auto im4m : _im4ms){ + for (auto im4m: _im4ms) { safeFree(im4m.first); } safeFree(_ibootBuild); safeFree(_firmwareJson); safeFree(_firmwareTokens); - safeFree(__latestManifest); - safeFree(__latestFirmwareUrl); - for (auto plist : _aptickets){ + safeFree(_latestManifest); + safeFree(_latestFirmwareUrl); + for (auto plist: _aptickets) { safeFreeCustom(plist, plist_free); } safeFreeCustom(_sepbuildmanifest, plist_free); safeFreeCustom(_basebandbuildmanifest, plist_free); } -void futurerestore::loadFirmwareTokens(){ - if (!_firmwareTokens){ +void futurerestore::loadFirmwareTokens() { + if (!_firmwareTokens) { if (!_firmwareJson) _firmwareJson = getFirmwareJson(); - retassure(_firmwareJson,"[TSSC] could not get firmware.json\n"); - int cnt = parseTokens(_firmwareJson, &_firmwareTokens); - retassure(cnt>0,"[TSSC] parsing %s.json failed\n",(0) ? "ota" : "firmware"); + retassure(_firmwareJson, "[TSSC] could not get firmware.json\n"); + long cnt = parseTokens(_firmwareJson, &_firmwareTokens); + retassure(cnt > 0, "[TSSC] parsing %s.json failed\n", (0) ? "ota" : "firmware"); } } -const char *futurerestore::getDeviceModelNoCopy(){ - if (!_client->device || !_client->device->product_type){ +const char *futurerestore::getDeviceModelNoCopy() { + if (!_client->device || !_client->device->product_type) { int mode = getDeviceMode(true); - retassure(mode == _MODE_NORMAL || mode == _MODE_RECOVERY || mode == _MODE_DFU, "unexpected device mode=%d\n",mode); + retassure(mode == _MODE_NORMAL || mode == _MODE_RECOVERY || mode == _MODE_DFU, "unexpected device mode=%d\n", + mode); switch (mode) { - case _MODE_RESTORE: - _client->device = restore_get_irecv_device(_client); - break; - case _MODE_NORMAL: - _client->device = normal_get_irecv_device(_client); - break; - case _MODE_DFU: - case _MODE_RECOVERY: - _client->device = dfu_get_irecv_device(_client); - break; - default: - break; + case _MODE_RESTORE: + _client->device = restore_get_irecv_device(_client); + break; + case _MODE_NORMAL: + _client->device = normal_get_irecv_device(_client); + break; + case _MODE_DFU: + case _MODE_RECOVERY: + _client->device = dfu_get_irecv_device(_client); + break; + default: + break; } } return _client->device->product_type; } -const char *futurerestore::getDeviceBoardNoCopy(){ - if (!_client->device || !_client->device->product_type){ +const char *futurerestore::getDeviceBoardNoCopy() { + if (!_client->device || !_client->device->product_type) { int mode = getDeviceMode(true); - retassure(mode == _MODE_NORMAL || mode == _MODE_RECOVERY || mode == _MODE_DFU, "unexpected device mode=%d\n",mode); - + retassure(mode == _MODE_NORMAL || mode == _MODE_RECOVERY || mode == _MODE_DFU, "unexpected device mode=%d\n", + mode); + switch (mode) { - case _MODE_RESTORE: - _client->device = restore_get_irecv_device(_client); - break; - case _MODE_NORMAL: - _client->device = normal_get_irecv_device(_client); - break; - case _MODE_DFU: - case _MODE_RECOVERY: - _client->device = dfu_get_irecv_device(_client); - break; - default: - break; + case _MODE_RESTORE: + _client->device = restore_get_irecv_device(_client); + break; + case _MODE_NORMAL: + _client->device = normal_get_irecv_device(_client); + break; + case _MODE_DFU: + case _MODE_RECOVERY: + _client->device = dfu_get_irecv_device(_client); + break; + default: + break; } } return _client->device->hardware_model; } -char *futurerestore::getLatestManifest(){ - if (!__latestManifest){ +char *futurerestore::getLatestManifest() { + if (!_latestManifest) { loadFirmwareTokens(); const char *device = getDeviceModelNoCopy(); t_iosVersion versVals; memset(&versVals, 0, sizeof(versVals)); - + int versionCnt = 0; int i = 0; char **versions = getListOfiOSForDevice(_firmwareTokens, device, 0, &versionCnt); retassure(versionCnt, "[TSSC] failed finding latest firmware version\n"); - char *bpos = NULL; - while((bpos = strstr((char*)(versVals.version = strdup(versions[i++])),"[B]")) != 0){ - free((char*)versVals.version); - if (--versionCnt == 0) reterror("[TSSC] automatic selection of firmware couldn't find for non-beta versions\n"); + char *bpos = nullptr; + while ((bpos = strstr((char *) (versVals.version = strdup(versions[i++])), "[B]")) != nullptr) { + free((char *) versVals.version); + if (--versionCnt == 0) + reterror("[TSSC] automatic selection of firmware couldn't find for non-beta versions\n"); } - info("[TSSC] selecting latest firmware version: %s\n",versVals.version); - if (bpos) *bpos= '\0'; - if (versions) free(versions[versionCnt-1]),free(versions); - - ptr_smartautofree(versVals.version); //make sure it get's freed after function finishes execution by either reaching end or throwing exception - - __latestFirmwareUrl = getFirmwareUrl(device, &versVals, _firmwareTokens); - retassure(__latestFirmwareUrl, "could not find url of latest firmware version\n"); - - __latestManifest = getBuildManifest(__latestFirmwareUrl, device, versVals.version, versVals.buildID, 0); - retassure(__latestManifest, "could not get buildmanifest of latest firmware version\n"); + info("[TSSC] selecting latest firmware version: %s\n", versVals.version); + if (bpos) *bpos = '\0'; + if (versions) free(versions[versionCnt - 1]), free(versions); + + ptr_smart autofree( + versVals.version); //make sure it gets freed after function finishes execution by either reaching end or throwing exception + + _latestFirmwareUrl = getFirmwareUrl(device, &versVals, _firmwareTokens); + retassure(_latestFirmwareUrl, "could not find url of latest firmware version\n"); + + _latestManifest = getBuildManifest(_latestFirmwareUrl, device, versVals.version, versVals.buildID, 0); + retassure(_latestManifest, "could not get buildmanifest of latest firmware version\n"); } - - return __latestManifest; + + return _latestManifest; } -char *futurerestore::getLatestFirmwareUrl(){ - return getLatestManifest(),__latestFirmwareUrl; +char *futurerestore::getLatestFirmwareUrl() { + return getLatestManifest(), _latestFirmwareUrl; } -void futurerestore::downloadLatestRose(){ - char * manifeststr = getLatestManifest(); - char *roseStr = (elemExists("Rap,RTKitOS", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Rap,RTKitOS", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - if(roseStr) { +void futurerestore::downloadLatestRose() { + char *manifeststr = getLatestManifest(); + char *roseStr = (elemExists("Rap,RTKitOS", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest( + "Rap,RTKitOS", manifeststr, getDeviceBoardNoCopy(), 0) : nullptr); + if (roseStr) { info("downloading Rose firmware\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), roseStr, _rosePath = ROSE_TMP_PATH), "could not download Rose\n"); - loadRose(ROSE_TMP_PATH); + retassure(!downloadPartialzip(getLatestFirmwareUrl(), roseStr, roseTempPath.c_str()), + "could not download Rose\n"); + loadRose(roseTempPath); } } -void futurerestore::downloadLatestSE(){ - char * manifeststr = getLatestManifest(); - char *seStr = (elemExists("SE,UpdatePayload", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("SE,UpdatePayload", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - if(seStr) { +void futurerestore::downloadLatestSE() { + char *manifeststr = getLatestManifest(); + char *seStr = (elemExists("SE,UpdatePayload", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest( + "SE,UpdatePayload", manifeststr, getDeviceBoardNoCopy(), 0) : nullptr); + if (seStr) { info("downloading SE firmware\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), seStr, _sePath = SE_TMP_PATH), "could not download SE\n"); - loadSE(SE_TMP_PATH); + retassure(!downloadPartialzip(getLatestFirmwareUrl(), seStr, seTempPath.c_str()), "could not download SE\n"); + loadSE(seTempPath); } } -void futurerestore::downloadLatestSavage(){ - char * manifeststr = getLatestManifest(); - char *savageB0ProdStr = (elemExists("Savage,B0-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Savage,B0-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - char *savageB0DevStr = (elemExists("Savage,B0-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Savage,B0-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - char *savageB2ProdStr = (elemExists("Savage,B2-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Savage,B2-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - char *savageB2DevStr = (elemExists("Savage,B2-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Savage,B2-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - char *savageBAProdStr = (elemExists("Savage,BA-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Savage,BA-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - char *savageBADevStr = (elemExists("Savage,BA-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("Savage,BA-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); +void futurerestore::downloadLatestSavage() { + char *manifeststr = getLatestManifest(); + char *savageB0ProdStr = (elemExists("Savage,B0-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("Savage,B0-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), + 0) : nullptr); + char *savageB0DevStr = (elemExists("Savage,B0-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("Savage,B0-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + : nullptr); + char *savageB2ProdStr = (elemExists("Savage,B2-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("Savage,B2-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), + 0) : nullptr); + char *savageB2DevStr = (elemExists("Savage,B2-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("Savage,B2-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + : nullptr); + char *savageBAProdStr = (elemExists("Savage,BA-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("Savage,BA-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), + 0) : nullptr); + char *savageBADevStr = (elemExists("Savage,BA-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("Savage,BA-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) + : nullptr); + std::array savagePaths{}; - if(savageB0ProdStr) { + if (savageB0ProdStr) { info("downloading Savage,B0-Prod-Patch\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB0ProdStr, _savagePath[0] = SAVAGE_B0_PP_TMP_PATH), "could not download Savage,B0-Prod-Patch\n"); + savagePaths[0] = futurerestoreTempPath + "/savageB0PP.fw"; + retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB0ProdStr, savagePaths[0].c_str()), + "could not download Savage,B0-Prod-Patch\n"); } - if(savageB0DevStr) { + if (savageB0DevStr) { info("downloading Savage,B0-Dev-Patch\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB0DevStr, _savagePath[1] = SAVAGE_B0_DP_TMP_PATH), "could not download Savage,B0-Dev-Patch\n"); + savagePaths[1] = futurerestoreTempPath + "//savageB0DP.fw"; + retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB0DevStr, savagePaths[1].c_str()), + "could not download Savage,B0-Dev-Patch\n"); } - if(savageB2ProdStr) { + if (savageB2ProdStr) { info("downloading Savage,B2-Prod-Patch\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB2ProdStr, _savagePath[2] = SAVAGE_B2_PP_TMP_PATH), "could not download Savage,B2-Prod-Patch\n"); + savagePaths[2] = futurerestoreTempPath + "//savageB2PP.fw"; + retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB2ProdStr, savagePaths[2].c_str()), + "could not download Savage,B2-Prod-Patch\n"); } - if(savageB2DevStr) { + if (savageB2DevStr) { info("downloading Savage,B2-Dev-Patch\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB2DevStr, _savagePath[3] = SAVAGE_B2_DP_TMP_PATH), "could not download Savage,B2-Dev-Patch\n"); + savagePaths[3] = futurerestoreTempPath + "//savageB2DP.fw"; + retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageB2DevStr, savagePaths[3].c_str()), + "could not download Savage,B2-Dev-Patch\n"); } - if(savageBAProdStr) { + if (savageBAProdStr) { info("downloading Savage,BA-Prod-Patch\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageBAProdStr, _savagePath[4] = SAVAGE_BA_PP_TMP_PATH), "could not download Savage,BA-Prod-Patch\n"); + savagePaths[4] = futurerestoreTempPath + "//savageBAPP.fw"; + retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageBAProdStr, savagePaths[4].c_str()), + "could not download Savage,BA-Prod-Patch\n"); } - if(savageBADevStr) { + if (savageBADevStr) { info("downloading Savage,BA-Dev-Patch\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageBADevStr, _savagePath[5] = SAVAGE_BA_DP_TMP_PATH), "could not download Savage,BA-Dev-Patch\n"); + savagePaths[5] = futurerestoreTempPath + "//savageBADP.fw"; + retassure(!downloadPartialzip(getLatestFirmwareUrl(), savageBADevStr, savagePaths[5].c_str()), + "could not download Savage,BA-Dev-Patch\n"); } - if( savageB0ProdStr && - savageB0DevStr && - savageB2ProdStr && - savageB2DevStr && - savageBAProdStr && - savageBADevStr) { - const char*savageArray[6] = {SAVAGE_B0_PP_TMP_PATH, SAVAGE_B0_DP_TMP_PATH, SAVAGE_B2_PP_TMP_PATH, SAVAGE_B2_DP_TMP_PATH, SAVAGE_BA_PP_TMP_PATH, SAVAGE_BA_DP_TMP_PATH}; - loadSavage(savageArray); + if (savageB0ProdStr && + savageB0DevStr && + savageB2ProdStr && + savageB2DevStr && + savageBAProdStr && + savageBADevStr) { + loadSavage(savagePaths); } } -void futurerestore::downloadLatestVeridian(){ - char * manifeststr = getLatestManifest(); - char *veridianDGMStr = (elemExists("BMU,DigestMap", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("BMU,DigestMap", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - char *veridianFWMStr = (elemExists("BMU,FirmwareMap", manifeststr, getDeviceBoardNoCopy(), 0) ? getPathOfElementInManifest("BMU,FirmwareMap", manifeststr, getDeviceBoardNoCopy(), 0) : NULL); - if(veridianDGMStr) { +void futurerestore::downloadLatestVeridian() { + char *manifeststr = getLatestManifest(); + char *veridianDGMStr = (elemExists("BMU,DigestMap", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("BMU,DigestMap", manifeststr, getDeviceBoardNoCopy(), 0) + : nullptr); + char *veridianFWMStr = (elemExists("BMU,FirmwareMap", manifeststr, getDeviceBoardNoCopy(), 0) + ? getPathOfElementInManifest("BMU,FirmwareMap", manifeststr, getDeviceBoardNoCopy(), 0) + : nullptr); + if (veridianDGMStr) { info("downloading Veridian DigestMap\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), veridianDGMStr, _veridianDGMPath = VERIDIAN_DGM_TMP_PATH), "could not download Veridian DigestMap\n"); + retassure(!downloadPartialzip(getLatestFirmwareUrl(), veridianDGMStr, veridianDGMTempPath.c_str()), + "could not download Veridian DigestMap\n"); } - if(veridianFWMStr) { + if (veridianFWMStr) { info("downloading Veridian FirmwareMap\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), veridianDGMStr, _veridianFWMPath = VERIDIAN_FWM_TMP_PATH), "could not download Veridian DigestMap\n"); + retassure(!downloadPartialzip(getLatestFirmwareUrl(), veridianDGMStr, veridianFWMTempPath.c_str()), + "could not download Veridian DigestMap\n"); } - if(veridianDGMStr && veridianFWMStr) - loadVeridian(VERIDIAN_DGM_TMP_PATH, VERIDIAN_FWM_TMP_PATH); + if (veridianDGMStr && veridianFWMStr) + loadVeridian(veridianDGMTempPath, veridianFWMTempPath); } -void futurerestore::downloadLatestFirmwareComponents(){ +void futurerestore::downloadLatestFirmwareComponents() { info("Downloading the latest firmware components...\n"); - char * manifeststr = getLatestManifest(); - if(elemExists("Rap,RTKitOS", manifeststr, getDeviceBoardNoCopy(), 0)) + char *manifeststr = getLatestManifest(); + if (elemExists("Rap,RTKitOS", manifeststr, getDeviceBoardNoCopy(), 0)) downloadLatestRose(); - if(elemExists("SE,UpdatePayload", manifeststr, getDeviceBoardNoCopy(), 0)) + if (elemExists("SE,UpdatePayload", manifeststr, getDeviceBoardNoCopy(), 0)) downloadLatestSE(); - if( elemExists("Savage,B0-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && - elemExists("Savage,B0-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && - elemExists("Savage,B2-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && - elemExists("Savage,B2-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && - elemExists("Savage,BA-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && - elemExists("Savage,BA-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0)) { + if (elemExists("Savage,B0-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && + elemExists("Savage,B0-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && + elemExists("Savage,B2-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && + elemExists("Savage,B2-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && + elemExists("Savage,BA-Prod-Patch", manifeststr, getDeviceBoardNoCopy(), 0) && + elemExists("Savage,BA-Dev-Patch", manifeststr, getDeviceBoardNoCopy(), 0)) { downloadLatestSavage(); } - if(elemExists("BMU,DigestMap", manifeststr, getDeviceBoardNoCopy(), 0) || elemExists("BMU,FirmwareMap", manifeststr, getDeviceBoardNoCopy(), 0)) + if (elemExists("BMU,DigestMap", manifeststr, getDeviceBoardNoCopy(), 0) || + elemExists("BMU,FirmwareMap", manifeststr, getDeviceBoardNoCopy(), 0)) downloadLatestVeridian(); info("Finished downloading the latest firmware components!\n"); } -void futurerestore::loadLatestBaseband(){ - char * manifeststr = getLatestManifest(); +void futurerestore::downloadLatestBaseband() { + char *manifeststr = getLatestManifest(); char *pathStr = getPathOfElementInManifest("BasebandFirmware", manifeststr, getDeviceBoardNoCopy(), 0); info("downloading Baseband\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathStr, _basebandPath = BASEBAND_TMP_PATH), "could not download baseband\n"); - saveStringToFile(manifeststr, BASEBAND_MANIFEST_TMP_PATH); - setBasebandManifestPath(BASEBAND_MANIFEST_TMP_PATH); - setBasebandPath(BASEBAND_TMP_PATH); + retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathStr, basebandTempPath.c_str()), + "could not download baseband\n"); + saveStringToFile(manifeststr, basebandManifestTempPath.c_str()); + setBasebandPath(basebandTempPath); + setBasebandPath(basebandManifestTempPath); + loadBaseband(basebandTempPath); + loadBasebandManifest(basebandManifestTempPath); } -void futurerestore::loadLatestSep(){ - char * manifeststr = getLatestManifest(); +void futurerestore::downloadLatestSep() { + char *manifeststr = getLatestManifest(); char *pathStr = getPathOfElementInManifest("SEP", manifeststr, getDeviceBoardNoCopy(), 0); info("downloading SEP\n\n"); - retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathStr, SEP_TMP_PATH), "could not download SEP\n"); - loadSep(SEP_TMP_PATH); - saveStringToFile(manifeststr, SEP_MANIFEST_TMP_PATH); - setSepManifestPath(SEP_MANIFEST_TMP_PATH); + retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathStr, sepTempPath.c_str()), "could not download SEP\n"); + loadSep(sepTempPath); + saveStringToFile(manifeststr, sepManifestTempPath.c_str()); + loadSepManifest(sepManifestTempPath); } -void futurerestore::setSepManifestPath(const char *sepManifestPath){ - retassure(_sepbuildmanifest = loadPlistFromFile(_sepbuildmanifestPath = sepManifestPath), "failed to load SEPManifest"); +void futurerestore::loadSepManifest(std::string sepManifestPath) { + this->_sepManifestPath = sepManifestPath; + retassure(_sepbuildmanifest = loadPlistFromFile(sepManifestPath.c_str()), + "failed to load SEP Manifest"); } -void futurerestore::setBasebandManifestPath(const char *basebandManifestPath){ - retassure(_basebandbuildmanifest = loadPlistFromFile(_basebandbuildmanifestPath = basebandManifestPath), "failed to load BasebandManifest"); +void futurerestore::loadBasebandManifest(std::string basebandManifestPath) { + this->_basebandManifestPath = basebandManifestPath; + retassure(_basebandbuildmanifest = loadPlistFromFile(basebandManifestPath.c_str()), + "failed to load Baseband Manifest"); }; -void futurerestore::loadRose(const char *rosePath){ - FILE *frose = NULL; - retassure(frose = fopen(rosePath, "rb"), "failed to read Rose\n"); - - fseek(frose, 0, SEEK_END); - _client->rosefwdatasize = ftell(frose); - fseek(frose, 0, SEEK_SET); - - retassure(_client->rosefwdata = (char*)malloc(_client->rosefwdatasize), "failed to malloc memory for Rose\n"); - - size_t freadRet=0; - retassure((freadRet = fread(_client->rosefwdata, 1, _client->rosefwdatasize, frose)) == _client->rosefwdatasize, - "failed to load Rose. size=%zu but fread returned %zu\n",_client->rosefwdatasize,freadRet); - - fclose(frose); +void futurerestore::loadRose(std::string rosePath) { + std::ifstream roseFileStream(rosePath); + retassure(roseFileStream.good(), "%s: failed init file stream for %s!\n", __func__, rosePath.c_str()); + roseFileStream.seekg(0, std::ios_base::end); + _client->rosefwdatasize = roseFileStream.tellg(); + roseFileStream.seekg(0, std::ios_base::beg); + retassure(_client->rosefwdata = (char *) calloc(_client->rosefwdatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, rosePath.c_str()); + roseFileStream.read((char *) _client->rosefwdata, + (std::streamsize) _client->rosefwdatasize); + retassure(*(uint64_t *) (_client->rosefwdata) != 0, + "%s: failed to load Rose for %s with the size %zu!\n", + __func__, rosePath.c_str(), _client->rosefwdatasize); } -void futurerestore::loadSE(const char *sePath){ - FILE *fse = NULL; - retassure(fse = fopen(sePath, "rb"), "failed to read SE\n"); - - fseek(fse, 0, SEEK_END); - _client->sefwdatasize = ftell(fse); - fseek(fse, 0, SEEK_SET); - - retassure(_client->sefwdata = (char*)malloc(_client->sefwdatasize), "failed to malloc memory for SE\n"); - - size_t freadRet=0; - retassure((freadRet = fread(_client->sefwdata, 1, _client->sefwdatasize, fse)) == _client->sefwdatasize, - "failed to load SE. size=%zu but fread returned %zu\n",_client->sefwdatasize,freadRet); - - fclose(fse); +void futurerestore::loadSE(std::string sePath) { + std::ifstream seFileStream(sePath); + retassure(seFileStream.good(), "%s: failed init file stream for %s!\n", __func__, sePath.c_str()); + seFileStream.seekg(0, std::ios_base::end); + _client->sefwdatasize = seFileStream.tellg(); + seFileStream.seekg(0, std::ios_base::beg); + retassure(_client->sefwdata = (char *) calloc(_client->sefwdatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, sePath.c_str()); + seFileStream.read((char *) _client->sefwdata, + (std::streamsize) _client->sefwdatasize); + retassure(*(uint64_t *) (_client->sefwdata) != 0, + "%s: failed to load SE for %s with the size %zu!\n", + __func__, sePath.c_str(), _client->sefwdatasize); } -void futurerestore::loadSavage(const char *savagePath[6]){ - for(int i = 0; i < 6; i++) { - FILE *fsavage = NULL; - retassure(fsavage = fopen(savagePath[i], "rb"), "failed to read Savage: %d\n", i); - - fseek(fsavage, 0, SEEK_END); - _client->savagefwdatasize[i] = ftell(fsavage); - fseek(fsavage, 0, SEEK_SET); - - retassure(_client->savagefwdata[i] = (char*)malloc(_client->savagefwdatasize[i]), "failed to malloc memory for Savage: %i\n", i); - - size_t freadRet=0; - retassure((freadRet = fread(_client->savagefwdata[i], 1, _client->savagefwdatasize[i], fsavage)) == _client->savagefwdatasize[i], - "failed to load Savage: %d. size=%zu but fread returned %zu\n",i,_client->savagefwdatasize[i],freadRet); - - fclose(fsavage); +void futurerestore::loadSavage(std::array savagePaths) { + int index = 0; + for (const auto &savagePath: savagePaths) { + std::ifstream savageFileStream(savagePath); + retassure(savageFileStream.good(), "%s: failed init file stream for %s!\n", __func__, savagePath.c_str()); + savageFileStream.seekg(0, std::ios_base::end); + _client->savagefwdatasize[index] = savageFileStream.tellg(); + savageFileStream.seekg(0, std::ios_base::beg); + retassure(_client->savagefwdata[index] = (char *) calloc(_client->savagefwdatasize[index], 1), + "%s: failed to calloc memory for %s\n", __func__, savagePath.c_str()); + savageFileStream.read((char *) _client->savagefwdata[index], + (std::streamsize) _client->savagefwdatasize[index]); + retassure(*(uint64_t *) (_client->savagefwdata[index]) != 0, + "%s: failed to load Savage for %s with the size %zu!\n", + __func__, savagePath.c_str(), _client->savagefwdatasize[index]); + index++; } } -void futurerestore::loadVeridian(const char *veridianDGMPath, const char *veridianFWMPath){ - FILE *fveridiandgm = NULL; - FILE *fveridianfwm = NULL; - retassure(fveridiandgm = fopen(veridianDGMPath, "rb"), "failed to read Veridian DigestMap\n"); - retassure(fveridianfwm = fopen(veridianFWMPath, "rb"), "failed to read Veridian FirmwareMap\n"); - - fseek(fveridiandgm, 0, SEEK_END); - fseek(fveridianfwm, 0, SEEK_END); - _client->veridiandgmfwdatasize = ftell(fveridiandgm); - _client->veridianfwmfwdatasize = ftell(fveridianfwm); - fseek(fveridiandgm, 0, SEEK_SET); - fseek(fveridianfwm, 0, SEEK_SET); - - retassure(_client->veridiandgmfwdata = (char*)malloc(_client->veridiandgmfwdatasize), "failed to malloc memory for Veridian DigestMap\n"); - retassure(_client->veridianfwmfwdata = (char*)malloc(_client->veridianfwmfwdatasize), "failed to malloc memory for Veridian FirmwareMap\n"); - - size_t freadRet=0; - retassure((freadRet = fread(_client->veridiandgmfwdata, 1, _client->veridiandgmfwdatasize, fveridiandgm)) == _client->veridiandgmfwdatasize, - "failed to load Veridian DigestMap. size=%zu but fread returned %zu\n",_client->veridiandgmfwdatasize,freadRet); - retassure((freadRet = fread(_client->sefwdata, 1, _client->veridianfwmfwdatasize, fveridianfwm)) == _client->veridianfwmfwdatasize, - "failed to load Veridian FirmwareMap. size=%zu but fread returned %zu\n",_client->veridianfwmfwdatasize,freadRet); - - fclose(fveridiandgm); - fclose(fveridianfwm); +void futurerestore::loadVeridian(std::string veridianDGMPath, std::string veridianFWMPath) { + std::ifstream veridianDGMFileStream(veridianDGMPath); + std::ifstream veridianFWMFileStream(veridianFWMPath); + retassure(veridianDGMFileStream.good(), "%s: failed init file stream for %s!\n", __func__, veridianDGMPath.c_str()); + retassure(veridianFWMFileStream.good(), "%s: failed init file stream for %s!\n", __func__, + veridianFWMPath.c_str()); + veridianDGMFileStream.seekg(0, std::ios_base::end); + _client->veridiandgmfwdatasize = veridianDGMFileStream.tellg(); + veridianDGMFileStream.seekg(0, std::ios_base::beg); + retassure(_client->veridiandgmfwdata = (char *) calloc(_client->veridiandgmfwdatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, veridianDGMPath.c_str()); + veridianDGMFileStream.read((char *) _client->veridiandgmfwdata, + (std::streamsize) _client->veridiandgmfwdatasize); + retassure(*(uint64_t *) (_client->veridiandgmfwdata) != 0, + "%s: failed to load Veridian for %s with the size %zu!\n", + __func__, veridianDGMPath.c_str(), _client->veridiandgmfwdatasize); + veridianFWMFileStream.seekg(0, std::ios_base::end); + _client->veridianfwmfwdatasize = veridianFWMFileStream.tellg(); + veridianFWMFileStream.seekg(0, std::ios_base::beg); + retassure(_client->veridianfwmfwdata = (char *) calloc(_client->veridianfwmfwdatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, veridianFWMPath.c_str()); + veridianFWMFileStream.read((char *) _client->veridianfwmfwdata, + (std::streamsize) _client->veridianfwmfwdatasize); + retassure(*(uint64_t *) (_client->veridianfwmfwdata) != 0, + "%s: failed to load Veridian for %s with the size %zu!\n", + __func__, veridianFWMPath.c_str(), _client->veridianfwmfwdatasize); } -void futurerestore::loadRamdisk(const char *ramdiskPath){ - FILE *framdisk = NULL; - retassure(framdisk = fopen(ramdiskPath, "rb"), "failed to read Ramdisk\n"); - - fseek(framdisk, 0, SEEK_END); - _client->ramdiskdatasize = ftell(framdisk); - fseek(framdisk, 0, SEEK_SET); - - retassure(_client->ramdiskdata = (char*)malloc(_client->ramdiskdatasize), "failed to malloc memory for Ramdisk\n"); - - size_t freadRet=0; - retassure((freadRet = fread(_client->ramdiskdata, 1, _client->ramdiskdatasize, framdisk)) == _client->ramdiskdatasize, - "failed to load Ramdisk. size=%zu but fread returned %zu\n",_client->ramdiskdatasize,freadRet); - - fclose(framdisk); +void futurerestore::loadRamdisk(std::string ramdiskPath) { + std::ifstream ramdiskFileStream(ramdiskPath); + retassure(ramdiskFileStream.good(), "%s: failed init file stream for %s!\n", __func__, ramdiskPath.c_str()); + ramdiskFileStream.seekg(0, std::ios_base::end); + _client->ramdiskdatasize = ramdiskFileStream.tellg(); + ramdiskFileStream.seekg(0, std::ios_base::beg); + retassure(_client->ramdiskdata = (char *) calloc(_client->ramdiskdatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, ramdiskPath.c_str()); + ramdiskFileStream.read((char *) _client->ramdiskdata, + (std::streamsize) _client->ramdiskdatasize); + retassure(*(uint64_t *) (_client->ramdiskdata) != 0, + "%s: failed to load Ramdisk for %s with the size %zu!\n", + __func__, ramdiskPath.c_str(), _client->ramdiskdatasize); } -void futurerestore::loadKernel(const char *loadKernel){ - FILE *fkernel = NULL; - retassure(fkernel = fopen(loadKernel, "rb"), "failed to read Kernel\n"); - - fseek(fkernel, 0, SEEK_END); - _client->kerneldatasize = ftell(fkernel); - fseek(fkernel, 0, SEEK_SET); - - retassure(_client->kerneldata = (char*)malloc(_client->kerneldatasize), "failed to malloc memory for Kernel\n"); - - size_t freadRet=0; - retassure((freadRet = fread(_client->kerneldata, 1, _client->kerneldatasize, fkernel)) == _client->kerneldatasize, - "failed to load Kernel. size=%zu but fread returned %zu\n",_client->kerneldatasize,freadRet); - - fclose(fkernel); +void futurerestore::loadKernel(std::string kernelPath) { + std::ifstream kernelFileStream(kernelPath); + retassure(kernelFileStream.good(), "%s: failed init file stream for %s!\n", __func__, kernelPath.c_str()); + kernelFileStream.seekg(0, std::ios_base::end); + _client->kerneldatasize = kernelFileStream.tellg(); + kernelFileStream.seekg(0, std::ios_base::beg); + retassure(_client->kerneldata = (char *) calloc(_client->kerneldatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, kernelPath.c_str()); + kernelFileStream.read((char *) _client->kerneldata, + (std::streamsize) _client->kerneldatasize); + retassure(*(uint64_t *) (_client->kerneldata) != 0, + "%s: failed to load Kernel for %s with the size %zu!\n", + __func__, kernelPath.c_str(), _client->kerneldatasize); } -void futurerestore::loadSep(const char *sepPath){ - FILE *fsep = NULL; - retassure(fsep = fopen(sepPath, "rb"), "failed to read SEP\n"); - - fseek(fsep, 0, SEEK_END); - _client->sepfwdatasize = ftell(fsep); - fseek(fsep, 0, SEEK_SET); - - retassure(_client->sepfwdata = (char*)malloc(_client->sepfwdatasize), "failed to malloc memory for SEP\n"); - - size_t freadRet=0; - retassure((freadRet = fread(_client->sepfwdata, 1, _client->sepfwdatasize, fsep)) == _client->sepfwdatasize, - "failed to load SEP. size=%zu but fread returned %zu\n",_client->sepfwdatasize,freadRet); - - fclose(fsep); +void futurerestore::loadSep(std::string sepPath) { + std::ifstream sepFileStream(sepPath); + retassure(sepFileStream.good(), "%s: failed init file stream for %s!\n", __func__, sepPath.c_str()); + sepFileStream.seekg(0, std::ios_base::end); + _client->sepfwdatasize = sepFileStream.tellg(); + sepFileStream.seekg(0, std::ios_base::beg); + retassure(_client->sepfwdata = (char *) calloc(_client->sepfwdatasize, 1), + "%s: failed to calloc memory for %s\n", __func__, sepPath.c_str()); + sepFileStream.read((char *) _client->sepfwdata, + (std::streamsize) _client->sepfwdatasize); + retassure(*(uint64_t *) (_client->sepfwdata) != 0, + "%s: failed to load SEP for %s with the size %zu!\n", + __func__, sepPath.c_str(), _client->sepfwdatasize); } -void futurerestore::setBasebandPath(const char *basebandPath){ - FILE *fbb = NULL; - - retassure(fbb = fopen(basebandPath, "rb"), "failed to read Baseband"); - _basebandPath = basebandPath; - fclose(fbb); -} - -void futurerestore::setRamdiskPath(const char *ramdiskPath) { - FILE *fbb = NULL; - - retassure(fbb = fopen(ramdiskPath, "rb"), "failed to read ramdisk"); - _ramdiskPath = ramdiskPath; - fclose(fbb); -} -void futurerestore::setKernelPath(const char *kernelPath) { - FILE *fbb = NULL; - - retassure(fbb = fopen(kernelPath, "rb"), "failed to read kernel"); - _kernelPath = kernelPath; - fclose(fbb); +void futurerestore::loadBaseband(std::string basebandPath) { + std::ifstream basebandFileStream(basebandPath); + retassure(basebandFileStream.good(), "%s: failed init file stream for %s!\n", __func__, basebandPath.c_str()); + basebandFileStream.seekg(0, std::ios_base::beg); + uint64_t *basebandFront = nullptr; + retassure(basebandFront = (uint64_t *) calloc(1, sizeof(uint64_t)), + "%s: failed to calloc memory for %s\n", __func__, basebandPath.c_str()); + basebandFileStream.read((char *)basebandFront, (std::streamsize)sizeof(uint64_t)); + retassure(*(uint64_t *) (basebandFront) != 0, "%s: failed to load Baseband for %s!\n", + __func__, basebandPath.c_str()); } #pragma mark static methods -inline void futurerestore::saveStringToFile(const char *str, const char *path){ - FILE *f = NULL; - retassure(f = fopen(path, "w"), "can't save file at %s\n",path); + +inline void futurerestore::saveStringToFile(const char *str, const char *path) { + FILE *f = nullptr; + retassure(f = fopen(path, "w"), "can't save file at %s\n", path); size_t len = strlen(str); size_t wlen = fwrite(str, 1, len, f); fclose(f); - retassure(len == wlen, "saving file failed, wrote=%zu actual=%zu\n",wlen,len); + retassure(len == wlen, "saving file failed, wrote=%zu actual=%zu\n", wlen, len); } -std::pair futurerestore::getNonceFromSCAB(const char* scab, size_t scabSize){ +std::pair futurerestore::getNonceFromSCAB(const char *scab, size_t scabSize) { retassure(scab, "Got empty SCAB\n"); - - img4tool::ASN1DERElement bacs(scab,scabSize); - + + img4tool::ASN1DERElement bacs(scab, scabSize); + try { bacs[3]; } catch (...) { reterror("unexpected number of Elements in SCAB sequence (expects 4)\n"); } - + img4tool::ASN1DERElement mainSet = bacs[1]; - for (auto &elem : mainSet) { - if (*(uint8_t*)elem.buf() == 0x92) { - return {(char*)elem.payload(),elem.payloadSize()}; + for (auto &elem: mainSet) { + if (*(uint8_t *) elem.buf() == 0x92) { + return {(char *) elem.payload(), elem.payloadSize()}; } } reterror("failed to get nonce from SCAB"); - return {NULL,0}; + return {NULL, 0}; } -uint64_t futurerestore::getEcidFromSCAB(const char* scab, size_t scabSize){ +uint64_t futurerestore::getEcidFromSCAB(const char *scab, size_t scabSize) { retassure(scab, "Got empty SCAB\n"); - - img4tool::ASN1DERElement bacs(scab,scabSize); - + + img4tool::ASN1DERElement bacs(scab, scabSize); + try { bacs[3]; } catch (...) { reterror("unexpected number of Elements in SCAB sequence (expects 4)\n"); } - + img4tool::ASN1DERElement mainSet = bacs[1]; - for (auto &elem : mainSet) { - if (*(uint8_t*)elem.buf() == 0x81) { + for (auto &elem: mainSet) { + if (*(uint8_t *) elem.buf() == 0x81) { uint64_t ret = 0; - for (int i=0; ifuturerestore::getRamdiskHashFromSCAB(const char* scab, size_t scabSize){ +std::pair futurerestore::getRamdiskHashFromSCAB(const char *scab, size_t scabSize) { retassure(scab, "Got empty SCAB\n"); - img4tool::ASN1DERElement bacs(scab,scabSize); + img4tool::ASN1DERElement bacs(scab, scabSize); try { bacs[3]; @@ -1808,55 +1819,56 @@ std::pairfuturerestore::getRamdiskHashFromSCAB(const char* img4tool::ASN1DERElement mainSet = bacs[1]; - for (auto &elem : mainSet) { - if (*(uint8_t*)elem.buf() == 0x9A) { - return {(char*)elem.payload(),elem.payloadSize()}; + for (auto &elem: mainSet) { + if (*(uint8_t *) elem.buf() == 0x9A) { + return {(char *) elem.payload(), elem.payloadSize()}; } } reterror("failed to get nonce from SCAB"); - return {NULL,0}; + return {NULL, 0}; } -plist_t futurerestore::loadPlistFromFile(const char *path){ - plist_t ret = NULL; - - FILE *f = fopen(path,"rb"); - if (!f){ - error("could not open file %s\n",path); - return NULL; +plist_t futurerestore::loadPlistFromFile(const char *path) { + plist_t ret = nullptr; + + FILE *f = fopen(path, "rb"); + if (!f) { + error("could not open file %s\n", path); + return nullptr; } fseek(f, 0, SEEK_END); size_t bufSize = ftell(f); fseek(f, 0, SEEK_SET); - - char *buf = (char*)malloc(bufSize); - if (!buf){ + + char *buf = (char *) malloc(bufSize); + if (!buf) { error("failed to alloc memory\n"); - return NULL; + return nullptr; } - + size_t freadRet = 0; - if ((freadRet = fread(buf, 1, bufSize, f)) != bufSize){ - error("fread=%zu but bufsize=%zu",freadRet,bufSize); - return NULL; + if ((freadRet = fread(buf, 1, bufSize, f)) != bufSize) { + error("fread=%zu but bufsize=%zu", freadRet, bufSize); + return nullptr; } fclose(f); - + if (memcmp(buf, "bplist00", 8) == 0) - plist_from_bin(buf, (uint32_t)bufSize, &ret); + plist_from_bin(buf, (uint32_t) bufSize, &ret); else - plist_from_xml(buf, (uint32_t)bufSize, &ret); + plist_from_xml(buf, (uint32_t) bufSize, &ret); free(buf); - + return ret; } -char *futurerestore::getPathOfElementInManifest(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall){ - char *pathStr = NULL; - ptr_smart buildmanifest(NULL,plist_free); - - plist_from_xml(manifeststr, (uint32_t)strlen(manifeststr), &buildmanifest); - +char *futurerestore::getPathOfElementInManifest(const char *element, const char *manifeststr, const char *boardConfig, + int isUpdateInstall) { + char *pathStr = nullptr; + ptr_smart buildmanifest(NULL, plist_free); + + plist_from_xml(manifeststr, (uint32_t) strlen(manifeststr), &buildmanifest); + if (plist_t identity = getBuildidentityWithBoardconfig(buildmanifest._p, boardConfig, isUpdateInstall)) if (plist_t manifest = plist_dict_get_item(identity, "Manifest")) if (plist_t elem = plist_dict_get_item(manifest, element)) @@ -1864,18 +1876,19 @@ char *futurerestore::getPathOfElementInManifest(const char *element, const char if (plist_t path = plist_dict_get_item(info, "Path")) if (plist_get_string_val(path, &pathStr), pathStr) goto noerror; - - reterror("could not get %s path\n",element); -noerror: + + reterror("could not get %s path\n", element); + noerror: return pathStr; } -bool futurerestore::elemExists(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall){ - char *pathStr = NULL; - ptr_smart buildmanifest(NULL,plist_free); - - plist_from_xml(manifeststr, (uint32_t)strlen(manifeststr), &buildmanifest); - +bool +futurerestore::elemExists(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall) { + char *pathStr = nullptr; + ptr_smart buildmanifest(NULL, plist_free); + + plist_from_xml(manifeststr, (uint32_t) strlen(manifeststr), &buildmanifest); + if (plist_t identity = getBuildidentityWithBoardconfig(buildmanifest._p, boardConfig, isUpdateInstall)) if (plist_t manifest = plist_dict_get_item(identity, "Manifest")) if (plist_t elem = plist_dict_get_item(manifest, element)) @@ -1883,28 +1896,29 @@ bool futurerestore::elemExists(const char *element, const char *manifeststr, con if (plist_t path = plist_dict_get_item(info, "Path")) if (plist_get_string_val(path, &pathStr), pathStr) goto noerror; - + return false; -noerror: + noerror: return true; } -std::string futurerestore::getGeneratorFromSHSH2(const plist_t shsh2){ - plist_t pGenerator = NULL; +std::string futurerestore::getGeneratorFromSHSH2(plist_t shsh2) { + plist_t pGenerator = nullptr; uint64_t gen = 0; - char *genstr = NULL; - cleanup([&]{ + char *genstr = nullptr; + cleanup([&] { safeFree(genstr); }); retassure(pGenerator = plist_dict_get_item(shsh2, "generator"), "signing ticket file does not contain generator"); - - retassure(plist_get_node_type(pGenerator) == PLIST_STRING, "generator has unexpected type! We expect string of the format 0x%16llx"); - + + retassure(plist_get_node_type(pGenerator) == PLIST_STRING, + "generator has unexpected type! We expect string of the format 0x%16llx"); + plist_get_string_val(pGenerator, &genstr); assure(genstr); - - sscanf(genstr, "0x%16llx",&gen); + + gen = std::stoul(genstr, nullptr, 16); retassure(gen, "failed to parse generator. Make sure it is in format 0x%16llx"); - + return {genstr}; } diff --git a/futurerestore/futurerestore.hpp b/futurerestore/futurerestore.hpp index 3df193cb..c00d3a86 100644 --- a/futurerestore/futurerestore.hpp +++ b/futurerestore/futurerestore.hpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -50,7 +52,7 @@ public: class futurerestore { struct idevicerestore_client_t* _client; - char *_ibootBuild = NULL; + char *_ibootBuild = nullptr; bool _didInit = false; vector _aptickets; vector>_im4ms; @@ -62,28 +64,23 @@ class futurerestore { bool _serial = false; bool _noRestore = false; - char *_firmwareJson = NULL; - jssytok_t *_firmwareTokens = NULL;; - char *__latestManifest = NULL; - char *__latestFirmwareUrl = NULL; + char *_firmwareJson = nullptr; + jssytok_t *_firmwareTokens = nullptr;; + char *_latestManifest = nullptr; + char *_latestFirmwareUrl = nullptr; - plist_t _sepbuildmanifest = NULL; - plist_t _basebandbuildmanifest = NULL; - - const char *_rosePath = NULL; - const char *_sePath = NULL; - const char *_savagePath[6]; - const char *_veridianDGMPath = NULL; - const char *_veridianFWMPath = NULL; + plist_t _sepbuildmanifest = nullptr; + plist_t _basebandbuildmanifest = nullptr; - const char *_basebandPath = NULL; - const char *_sepbuildmanifestPath = NULL; - const char *_basebandbuildmanifestPath = NULL; - const char *_ramdiskPath = NULL; - const char *_kernelPath = NULL; + std::string _ramdiskPath; + std::string _kernelPath; + std::string _sepPath; + std::string _sepManifestPath; + std::string _basebandPath; + std::string _basebandManifestPath; - const char *_custom_nonce = NULL; - const char *_boot_args = NULL; + const char *_custom_nonce = nullptr; + const char *_boot_args = nullptr; bool _noCache = false; bool _skipBlob = false; @@ -92,8 +89,7 @@ class futurerestore { bool _rerestoreiOS9 = false; //methods void enterPwnRecovery(plist_t build_identity, std::string bootargs); - void enterPwnRecovery2(plist_t build_identity, std::string bootargs = ""); - + public: futurerestore(bool isUpdateInstall = false, bool isPwnDfu = false, bool noIBSS = false, bool setNonce = false, bool serial = false, bool noRestore = false); bool init(); @@ -115,43 +111,44 @@ public: const char *getDeviceBoardNoCopy(); char *getLatestManifest(); char *getLatestFirmwareUrl(); + std::string getSepManifestPath(){return _sepManifestPath;} + std::string getBasebandManifestPath(){return _basebandManifestPath;} void downloadLatestRose(); void downloadLatestSE(); void downloadLatestSavage(); void downloadLatestVeridian(); void downloadLatestFirmwareComponents(); - void loadLatestBaseband(); - void loadLatestSep(); + void downloadLatestBaseband(); + void downloadLatestSep(); - void setSepManifestPath(const char *sepManifestPath); - void setBasebandManifestPath(const char *basebandManifestPath); - void loadRose(const char *rosePath); - void loadSE(const char *sePath); - void loadSavage(const char *savagePath[6]); - void loadVeridian(const char *veridianDGMPath, const char *veridianFWMPath); - void loadRamdisk(const char *ramdiskPath); - void loadKernel(const char *kernelPath); - void loadSep(const char *sepPath); - void setBasebandPath(const char *basebandPath); - void setRamdiskPath(const char *ramdiskPath); - void setKernelPath(const char *kernelPath); + void loadSepManifest(std::string sepManifestPath); + void loadBasebandManifest(std::string basebandManifestPath); + void loadRose(std::string rosePath); + void loadSE(std::string sePath); + void loadSavage(std::array savagePaths); + void loadVeridian(std::string veridianDGMPath, std::string veridianFWMPath); + void loadRamdisk(std::string ramdiskPath); + void loadKernel(std::string kernelPath); + void loadSep(std::string sepPath); + void loadBaseband(std::string basebandPath); + + void setSepPath(std::string sepPath) {_sepPath = sepPath;} + void setSepManifestPath(std::string sepManifestPath) {_sepManifestPath = sepManifestPath;} + void setRamdiskPath(std::string ramdiskPath) {_ramdiskPath = ramdiskPath;} + void setKernelPath(std::string kernelPath) {_kernelPath = kernelPath;} + void setBasebandPath(std::string basebandPath) {_basebandPath = basebandPath;} + void setBasebandManifestPath(std::string basebandManifestPath) {_basebandManifestPath = basebandManifestPath;} void setNonce(const char *custom_nonce){_custom_nonce = custom_nonce;}; void setBootArgs(const char *boot_args){_boot_args = boot_args;}; void disableCache(){_noCache = true;}; void skipBlobValidation(){_skipBlob = true;}; - bool isUpdateInstall(){return _isUpdateInstall;}; - - plist_t sepManifest(){return _sepbuildmanifest;}; - plist_t basebandManifest(){return _basebandbuildmanifest;}; - const char *sepManifestPath(){return _sepbuildmanifestPath;}; - const char *basebandManifestPath(){return _basebandbuildmanifestPath;}; + bool is32bit(){return !is_image4_supported(_client);}; uint64_t getBasebandGoldCertIDFromDevice(); void doRestore(const char *ipsw); - int doJustBoot(const char *ipsw, std::string bootargs = ""); - + ~futurerestore(); static std::pair getRamdiskHashFromSCAB(const char* scab, size_t scabSize); @@ -160,8 +157,8 @@ public: static plist_t loadPlistFromFile(const char *path); static void saveStringToFile(const char *str, const char *path); static char *getPathOfElementInManifest(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall); - bool elemExists(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall); - static std::string getGeneratorFromSHSH2(const plist_t shsh2); + static bool elemExists(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall); + static std::string getGeneratorFromSHSH2(plist_t shsh2); }; #endif /* futurerestore_hpp */ diff --git a/futurerestore/main.cpp b/futurerestore/main.cpp index c56ad993..38a15a82 100644 --- a/futurerestore/main.cpp +++ b/futurerestore/main.cpp @@ -6,11 +6,7 @@ // Copyright © 2016 tihmstar. All rights reserved. // -#include #include -#include -#include -#include #include "futurerestore.hpp" extern "C"{ @@ -34,31 +30,31 @@ extern "C"{ #endif static struct option longopts[] = { - { "apticket", required_argument, NULL, 't' }, - { "baseband", required_argument, NULL, 'b' }, - { "baseband-manifest", required_argument, NULL, 'p' }, - { "sep", required_argument, NULL, 's' }, - { "sep-manifest", required_argument, NULL, 'm' }, - { "wait", no_argument, NULL, 'w' }, - { "update", no_argument, NULL, 'u' }, - { "debug", no_argument, NULL, 'd' }, - { "exit-recovery", no_argument, NULL, 'e' }, - { "latest-sep", no_argument, NULL, '0' }, - { "no-restore", no_argument, NULL, 'z' }, - { "latest-baseband", no_argument, NULL, '1' }, - { "no-baseband", no_argument, NULL, '2' }, + { "apticket", required_argument, nullptr, 't' }, + { "baseband", required_argument, nullptr, 'b' }, + { "baseband-manifest", required_argument, nullptr, 'p' }, + { "sep", required_argument, nullptr, 's' }, + { "sep-manifest", required_argument, nullptr, 'm' }, + { "wait", no_argument, nullptr, 'w' }, + { "update", no_argument, nullptr, 'u' }, + { "debug", no_argument, nullptr, 'd' }, + { "exit-recovery", no_argument, nullptr, 'e' }, + { "latest-sep", no_argument, nullptr, '0' }, + { "no-restore", no_argument, nullptr, 'z' }, + { "latest-baseband", no_argument, nullptr, '1' }, + { "no-baseband", no_argument, nullptr, '2' }, #ifdef HAVE_LIBIPATCHER - { "use-pwndfu", no_argument, NULL, '3' }, - { "no-ibss", no_argument, NULL, '4' }, - { "rdsk", required_argument, NULL, '5' }, - { "rkrn", required_argument, NULL, '6' }, - { "set-nonce", optional_argument, NULL, '7' }, - { "serial", no_argument, NULL, '8' }, - { "boot-args", required_argument, NULL, '9' }, - { "no-cache", no_argument, NULL, 'a' }, - { "skip-blob", no_argument, NULL, 'c' }, + { "use-pwndfu", no_argument, nullptr, '3' }, + { "no-ibss", no_argument, nullptr, '4' }, + { "rdsk", required_argument, nullptr, '5' }, + { "rkrn", required_argument, nullptr, '6' }, + { "set-nonce", optional_argument, nullptr, '7' }, + { "serial", no_argument, nullptr, '8' }, + { "boot-args", required_argument, nullptr, '9' }, + { "no-cache", no_argument, nullptr, 'a' }, + { "skip-blob", no_argument, nullptr, 'c' }, #endif - { NULL, 0, NULL, 0 } + { nullptr, 0, nullptr, 0 } }; #define FLAG_WAIT 1 << 0 @@ -136,28 +132,24 @@ int main_r(int argc, const char * argv[]) { #endif int optindex = 0; - int opt = 0; + int opt; long flags = 0; bool exitRecovery = false; - bool noRestore = false; - int isSepManifestSigned = 0; - int isBasebandSigned = 0; - - const char *ipsw = NULL; - const char *basebandPath = NULL; - const char *basebandManifestPath = NULL; - const char *sepPath = NULL; - const char *sepManifestPath = NULL; - const char *bootargs = NULL; - const char *ramdiskPath = NULL; - const char *kernelPath = NULL; - const char *custom_nonce = NULL; + const char *ipsw = nullptr; + const char *basebandPath = nullptr; + const char *basebandManifestPath = nullptr; + const char *sepPath = nullptr; + const char *sepManifestPath = nullptr; + const char *bootargs = nullptr; + const char *ramdiskPath = nullptr; + const char *kernelPath = nullptr; + const char *custom_nonce = nullptr; vector apticketPaths; - t_devicevals devVals = {0}; - t_iosVersion versVals = {0}; + t_devicevals devVals = {nullptr}; + t_iosVersion versVals = {nullptr}; if (argc == 1){ cmd_help(); @@ -213,11 +205,11 @@ int main_r(int argc, const char * argv[]) { break; case '7': // long option: "set-nonce"; flags |= FLAG_SET_NONCE; - custom_nonce = (optarg) ? optarg : NULL; - if(custom_nonce != NULL) { + custom_nonce = (optarg) ? optarg : nullptr; + if(custom_nonce != nullptr) { uint64_t gen; retassure(strlen(custom_nonce) == 16 || strlen(custom_nonce) == 18,"Incorrect nonce length!\n"); - sscanf(custom_nonce, "0x%16llx",&gen); + gen = std::stoul(custom_nonce, nullptr, 16); retassure(gen, "failed to parse generator. Make sure it is in format 0x%16llx"); } break; @@ -226,7 +218,7 @@ int main_r(int argc, const char * argv[]) { break; case '9': // long option: "boot-args"; flags |= FLAG_BOOT_ARGS; - bootargs = (optarg) ? optarg : NULL; + bootargs = (optarg) ? optarg : nullptr; break; case 'a': // long option: "no-cache"; flags |= FLAG_NO_CACHE; @@ -251,7 +243,6 @@ int main_r(int argc, const char * argv[]) { } if (argc-optind == 1) { - argc -= optind; argv += optind; ipsw = argv[0]; @@ -303,10 +294,12 @@ int main_r(int argc, const char * argv[]) { } try { - if (apticketPaths.size()) client.loadAPTickets(apticketPaths); + if (!apticketPaths.empty()) { + client.loadAPTickets(apticketPaths); + } if (!( - ((apticketPaths.size() && ipsw) + ((!apticketPaths.empty() && ipsw) && ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND))) && ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit()) ) || (ipsw && (flags & FLAG_IS_PWN_DFU)) @@ -355,14 +348,14 @@ int main_r(int argc, const char * argv[]) { if (flags & FLAG_LATEST_SEP){ info("user specified to use latest signed SEP\n"); - client.loadLatestSep(); + client.downloadLatestSep(); }else if (!client.is32bit()){ client.loadSep(sepPath); - client.setSepManifestPath(sepManifestPath); + client.loadSepManifest(sepManifestPath); } versVals.basebandMode = kBasebandModeWithoutBaseband; - if (!client.is32bit() && !(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), &devVals, &versVals, NULL))){ + if (!client.is32bit() && !(isManifestSignedForDevice(client.getSepManifestPath().c_str(), &devVals, &versVals, nullptr))){ reterror("SEP firmware is NOT being signed!\n"); } if (flags & FLAG_NO_BASEBAND){ @@ -379,10 +372,10 @@ int main_r(int argc, const char * argv[]) { }else{ if (flags & FLAG_LATEST_BASEBAND){ info("user specified to use latest signed baseband\n"); - client.loadLatestBaseband(); + client.downloadLatestBaseband(); }else{ client.setBasebandPath(basebandPath); - client.setBasebandManifestPath(basebandManifestPath); + client.loadBasebandManifest(basebandManifestPath); printf("Did set SEP+baseband path and firmware\n"); } @@ -390,7 +383,7 @@ int main_r(int argc, const char * argv[]) { if (!(devVals.bbgcid = client.getBasebandGoldCertIDFromDevice())){ printf("[WARNING] using tsschecker's fallback to get BasebandGoldCertID. This might result in invalid baseband signing status information\n"); } - if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), &devVals, &versVals, NULL))) { + if (!(isManifestSignedForDevice(client.getBasebandManifestPath().c_str(), &devVals, &versVals, nullptr))) { reterror("baseband firmware is NOT being signed!\n"); } }