int get_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size) { *nonce = NULL; *nonce_size = 0; switch (client->mode->index) { case MODE_NORMAL: error("ERROR: Can't get nonce in Normal mode\n"); return -1; case MODE_DFU: if (dfu_get_nonce(client, nonce, nonce_size) < 0) { return -1; } break; case MODE_RECOVERY: if (recovery_get_nonce(client, nonce, nonce_size) < 0) { return -1; } break; default: error("ERROR: Device is in an invalid state\n"); return -1; } return 0; }
int get_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size) { *nonce = NULL; *nonce_size = 0; info("Getting nonce "); switch (client->mode->index) { case MODE_NORMAL: info("in normal mode... "); if (normal_get_nonce(client, nonce, nonce_size) < 0) { info("failed\n"); return -1; } break; case MODE_DFU: info("in dfu mode... "); if (dfu_get_nonce(client, nonce, nonce_size) < 0) { info("failed\n"); return -1; } break; case MODE_RECOVERY: info("in recovery mode... "); if (recovery_get_nonce(client, nonce, nonce_size) < 0) { info("failed\n"); return -1; } break; default: error("ERROR: Device is in an invalid state\n"); return -1; } int i = 0; for (i = 0; i < *nonce_size; i++) { info("%02x ", (*nonce)[i]); } info("\n"); return 0; }
int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) { irecv_error_t dfu_error = IRECV_E_SUCCESS; if (dfu_client_new(client) < 0) { error("ERROR: Unable to connect to DFU device\n"); return -1; } if (client->dfu->client->mode != kDfuMode) { info("NOTE: device is not in DFU mode, assuming recovery mode.\n"); client->mode = &idevicerestore_modes[MODE_RECOVERY]; return 0; } if (dfu_send_component(client, build_identity, "iBSS") < 0) { error("ERROR: Unable to send iBSS to device\n"); irecv_close(client->dfu->client); return -1; } dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); return -1; } if (client->build[0] > '8') { /* reconnect */ dfu_client_free(client); sleep(1); dfu_client_new(client); /* get nonce */ unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (dfu_get_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get nonce from device!\n"); return -1; } if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) { nonce_changed = 1; if (client->nonce) { free(client->nonce); } client->nonce = nonce; client->nonce_size = nonce_size; } else { free(nonce); } info("Nonce: "); int i; for (i = 0; i < client->nonce_size; i++) { info("%02x ", client->nonce[i]); } info("\n"); if (nonce_changed && !(client->flags & FLAG_CUSTOM)) { // Welcome iOS5. We have to re-request the TSS with our nonce. plist_free(client->tss); if (get_shsh_blobs(client, client->ecid, client->nonce, client->nonce_size, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } if (!client->tss) { error("ERROR: can't continue without TSS\n"); return -1; } fixup_tss(client->tss); } if (irecv_set_configuration(client->dfu->client, 1) < 0) { error("ERROR: set configuration failed\n"); } /* send iBEC */ if (dfu_send_component(client, build_identity, "iBEC") < 0) { error("ERROR: Unable to send iBEC to device\n"); irecv_close(client->dfu->client); return -1; } dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); return -1; } } dfu_client_free(client); sleep(7); // Reconnect to device, but this time make sure we're not still in DFU mode if (recovery_client_new(client) < 0 || client->recovery->client->mode == kDfuMode) { error("ERROR: Unable to connect to recovery device\n"); if (client->recovery->client) irecv_close(client->recovery->client); return -1; } return 0; }