From 5232e5a5a421aacbb46a9f59282262a7832fe00b Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Tue, 17 Jul 2012 16:40:31 +0200 Subject: restore: added .mbn file support and bbfw handling --- src/Makefile.am | 2 +- src/mbn.c | 77 +++++++ src/mbn.h | 52 +++++ src/restore.c | 606 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 656 insertions(+), 81 deletions(-) create mode 100644 src/mbn.c create mode 100644 src/mbn.h diff --git a/src/Makefile.am b/src/Makefile.am index 15d2552..680e43f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,7 +20,7 @@ AM_LDADD = $(AC_LDADD) bin_PROGRAMS = idevicerestore -idevicerestore_SOURCES = idevicerestore.c common.c tss.c fls.c img3.c ipsw.c normal.c dfu.c recovery.c restore.c asr.c limera1n.c download.c locking.c +idevicerestore_SOURCES = idevicerestore.c common.c tss.c fls.c mbn.c img3.c ipsw.c normal.c dfu.c recovery.c restore.c asr.c limera1n.c download.c locking.c idevicerestore_CFLAGS = $(AM_CFLAGS) idevicerestore_LDFLAGS = $(AM_LDFLAGS) idevicerestore_LDADD = $(AM_LDADD) diff --git a/src/mbn.c b/src/mbn.c new file mode 100644 index 0000000..0e76425 --- /dev/null +++ b/src/mbn.c @@ -0,0 +1,77 @@ +/* + * mbn.c + * support for .mbn file format (found in .bbfw files) + * + * Copyright (c) 2012 Nikias Bassen. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include "mbn.h" +#include "common.h" + +mbn_file* mbn_parse(unsigned char* data, unsigned int size) +{ + mbn_file* mbn = (mbn_file*)malloc(sizeof(mbn_file)); + if (!mbn) { + return NULL; + } + memset(mbn, '\0', sizeof(mbn_file)); + mbn->data = malloc(size); + mbn->size = size; + memcpy(mbn->data, data, size); + /* FIXME: header parsing is not big endian safe */ + memcpy(&mbn->header, data, sizeof(mbn_header)); + mbn->parsed_size = mbn->header.data_size + sizeof(mbn_header); + mbn->parsed_sig_offset = mbn->header.sig_offset - (mbn->header.data_size & 0xFF); + if (mbn->parsed_size != mbn->size) { + printf("size mismatch?!\n"); + } + return mbn; +} + +void mbn_free(mbn_file* mbn) +{ + if (mbn) { + if (mbn->data) { + free(mbn->data); + } + free(mbn); + } +} + +int mbn_update_sig_blob(mbn_file* mbn, const unsigned char* sigdata, unsigned int siglen) +{ + if (!mbn) { + error("ERROR: %s: no data\n", __func__); + return -1; + } + if (!mbn->parsed_sig_offset || (mbn->parsed_sig_offset >= mbn->parsed_size)) { + error("ERROR: %s: invalid signature offset in mbn header\n", __func__); + return -1; + } + + if ((mbn->parsed_sig_offset + siglen) > mbn->parsed_size) { + error("ERROR: %s: signature is larger than mbn file size\n", __func__); + return -1; + } + + memcpy(mbn->data + mbn->parsed_sig_offset, sigdata, siglen); + + return 0; +} + diff --git a/src/mbn.h b/src/mbn.h new file mode 100644 index 0000000..a42a45b --- /dev/null +++ b/src/mbn.h @@ -0,0 +1,52 @@ +/* + * mbn.h + * support for .mbn file format (found in .bbfw files) + * + * Copyright (c) 2012 Nikias Bassen. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef MBN_H +#define MBN_H + +#include + +struct _mbn_header { + uint32_t type; // the signed .mbn files have 0xA as value. + uint32_t unk_0x04; + uint32_t unk_0x08; + uint32_t unk_0x0c; + uint32_t data_size; // data_size = total_size - sizeof(mbn_header) + uint32_t sig_offset; // real offset = enc_sig_offset & 0xFFFFFF00 + uint32_t unk_0x18; + uint32_t unk_0x1c; + uint32_t unk_0x20; + uint32_t unk_0x24; +} __attribute__((packed)); +typedef struct _mbn_header mbn_header; + +typedef struct { + mbn_header header; + uint32_t parsed_size; + uint32_t parsed_sig_offset; + void* data; + uint32_t size; +} mbn_file; + +mbn_file* mbn_parse(unsigned char* data, unsigned int size); +void mbn_free(mbn_file* mbn); +int mbn_update_sig_blob(mbn_file* mbn, const unsigned char* data, unsigned int size); + +#endif diff --git a/src/restore.c b/src/restore.c index 77b658e..62e33f4 100644 --- a/src/restore.c +++ b/src/restore.c @@ -27,6 +27,7 @@ #include "asr.h" #include "fls.h" +#include "mbn.h" #include "tss.h" #include "common.h" #include "restore.h" @@ -785,55 +786,428 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* return 0; } -int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) +static int restore_handle_trek_bbfw(const char* bbfwtmp, plist_t response, unsigned char* bb_nonce) { int res = -1; - uint64_t bb_cert_id = 0; - unsigned char* bb_snum = NULL; - uint64_t bb_snum_size = 0; - unsigned char* bb_nonce = NULL; - uint64_t bb_nonce_size = 0; - // setup request data - plist_t arguments = plist_dict_get_item(message, "Arguments"); - if (arguments && plist_get_node_type(arguments) == PLIST_DICT) { - plist_t bb_cert_id_node = plist_dict_get_item(arguments, "CertID"); - if (bb_cert_id_node && plist_get_node_type(bb_cert_id_node) == PLIST_UINT) { - plist_get_uint_val(bb_cert_id_node, &bb_cert_id); - } - plist_t bb_snum_node = plist_dict_get_item(arguments, "ChipSerialNo"); - if (bb_snum_node && plist_get_node_type(bb_snum_node) == PLIST_DATA) { - plist_get_data_val(bb_snum_node, (char**)&bb_snum, &bb_snum_size); - } - plist_t bb_nonce_node = plist_dict_get_item(arguments, "Nonce"); - if (bb_nonce_node && plist_get_node_type(bb_nonce_node) == PLIST_DATA) { - plist_get_data_val(bb_nonce_node, (char**)&bb_nonce, &bb_nonce_size); - } + // check for BBTicket in result + plist_t bbticket = plist_dict_get_item(response, "BBTicket"); + if (!bbticket || plist_get_node_type(bbticket) != PLIST_DATA) { + error("ERROR: Could not find BBTicket in Baseband TSS response\n"); + return -1; } - // create Baseband TSS request - plist_t request = tss_create_baseband_request(build_identity, client->ecid, bb_cert_id, bb_snum, bb_snum_size, bb_nonce, bb_nonce_size); - if (request == NULL) { - error("ERROR: Unable to create Baseand TSS request\n"); + // check for eDBL-Blob in result + plist_t edbl = plist_access_path(response, 2, "BasebandFirmware", "eDBL-Blob"); + if (!edbl || plist_get_node_type(edbl) != PLIST_DATA) { + error("ERROR: Could not find eDBL-Blob in Baseband TSS response\n"); return -1; } - // send Baseband TSS request - debug_plist(request); - info("Sending Baseband TSS request... "); - plist_t response = tss_send_request(request); - plist_free(request); - if (response == NULL) { - error("ERROR: Unable to fetch Baseband TSS\n"); + // check for RestoreDBL-Blob in result + plist_t restoredbl = plist_access_path(response, 2, "BasebandFirmware", "RestoreDBL-Blob"); + if (!restoredbl || plist_get_node_type(restoredbl) != PLIST_DATA) { + error("ERROR: Could not find FlashPSI-Blob in Baseband TSS response\n"); return -1; } - debug_plist(response); + + unsigned char* buffer = NULL; + unsigned char* blob = NULL; + unsigned char* mbndata = NULL; + off_t mbnsize = 0; + uint64_t blob_size = 0; + int zerr = 0; + int zindex = -1; + int size = 0; + struct zip_stat zstat; + struct zip_file* zfile = NULL; + struct zip* za = NULL; + struct zip_source* zs = NULL; + mbn_file* mbn = NULL; + int dbl_index = -1; + int restoredbl_index = -1; + + za = zip_open(bbfwtmp, 0, &zerr); + if (!za) { + error("ERROR: Could not open ZIP archive '%s': %d\n", bbfwtmp, zerr); + goto leave; + } + + if (!bb_nonce) { + // first time call + // sign dbl.mbn + zindex = zip_name_locate(za, "dbl.mbn", 0); + if (zindex < 0) { + error("ERROR: can't locate 'dbl.mbn' in '%s'\n", bbfwtmp); + goto leave; + } + + zip_stat_init(&zstat); + if (zip_stat_index(za, zindex, 0, &zstat) != 0) { + error("ERROR: zip_stat_index failed for index %d\n", zindex); + goto leave; + } + + zfile = zip_fopen_index(za, zindex, 0); + if (zfile == NULL) { + error("ERROR: zip_fopen_index failed for index %d\n", zindex); + goto leave; + } + + size = zstat.size; + buffer = (unsigned char*) malloc(size+1); + if (buffer == NULL) { + error("ERROR: Out of memory\n"); + goto leave; + } + + if (zip_fread(zfile, buffer, size) != size) { + error("ERROR: zip_fread: failed\n"); + goto leave; + } + buffer[size] = '\0'; + + zip_fclose(zfile); + zfile = NULL; + + mbn = mbn_parse(buffer, size); + free(buffer); + buffer = NULL; + if (!mbn) { + error("ERROR: could not parse mbn file\n"); + goto leave; + } + + blob = NULL; + blob_size = 0; + plist_get_data_val(edbl, (char**)&blob, &blob_size); + if (!blob) { + error("ERROR: could not get eDBL-Blob data\n"); + goto leave; + } + + if (mbn_update_sig_blob(mbn, blob, (unsigned int)blob_size) != 0) { + error("ERROR: could not sign dbl.mbn\n"); + goto leave; + } + free(blob); + blob = NULL; + + mbnsize = mbn->size; + mbndata = (unsigned char*)malloc(mbnsize); + memcpy(mbndata, mbn->data, mbnsize); + mbn_free(mbn); + mbn = NULL; + + zs = zip_source_buffer(za, mbndata, mbnsize, 1); + if (!zs) { + error("ERROR: out of memory\n"); + goto leave; + } + + if (zip_replace(za, zindex, zs) == -1) { + error("ERROR: could not add signed dbl.mbn to archive\n"); + goto leave; + } + dbl_index = zindex; + + // sign restoredbl.mbn + zindex = zip_name_locate(za, "restoredbl.mbn", 0); + if (zindex < 0) { + error("ERROR: can't locate 'restoredbl.mbn' in '%s'\n", bbfwtmp); + goto leave; + } + + zip_stat_init(&zstat); + if (zip_stat_index(za, zindex, 0, &zstat) != 0) { + error("ERROR: zip_stat_index failed for index %d\n", zindex); + goto leave; + } + + zfile = zip_fopen_index(za, zindex, 0); + if (zfile == NULL) { + error("ERROR: zip_fopen_index failed for index %d\n", zindex); + goto leave; + } + + size = zstat.size; + buffer = (unsigned char*) malloc(size+1); + if (buffer == NULL) { + error("ERROR: Out of memory\n"); + goto leave; + } + + if (zip_fread(zfile, buffer, size) != size) { + error("ERROR: zip_fread: failed\n"); + goto leave; + } + buffer[size] = '\0'; + + zip_fclose(zfile); + zfile = NULL; + + mbn = mbn_parse(buffer, size); + free(buffer); + buffer = NULL; + if (!mbn) { + error("ERROR: could not parse mbn file\n"); + goto leave; + } + + blob = NULL; + blob_size = 0; + plist_get_data_val(restoredbl, (char**)&blob, &blob_size); + if (!blob) { + error("ERROR: could not get RestoreDBL-Blob data\n"); + goto leave; + } + + if (mbn_update_sig_blob(mbn, blob, (unsigned int)blob_size) != 0) { + error("ERROR: could not sign restoredbl.mbn\n"); + goto leave; + } + free(blob); + blob = NULL; + + mbnsize = mbn->size; + mbndata = (unsigned char*)malloc(mbnsize); + memcpy(mbndata, mbn->data, mbnsize); + mbn_free(mbn); + mbn = NULL; + + zs = zip_source_buffer(za, mbndata, mbnsize, 1); + if (!zs) { + error("ERROR: out of memory\n"); + goto leave; + } + + if (zip_replace(za, zindex, zs) == -1) { + error("ERROR: could not add signed dbl.mbn to archive\n"); + goto leave; + } + restoredbl_index = zindex; + + // remove all other files from zip + int i; + int numf = zip_get_num_files(za); + for (i = 0; i < numf; i++) { + if ((i == dbl_index) || (i == restoredbl_index)) { + continue; + } + zip_delete(za, i); + } + } else { + // second time call + // sign dbl.mbn + zindex = zip_name_locate(za, "dbl.mbn", 0); + if (zindex < 0) { + error("ERROR: can't locate 'dbl.mbn' in '%s'\n", bbfwtmp); + goto leave; + } + + zip_stat_init(&zstat); + if (zip_stat_index(za, zindex, 0, &zstat) != 0) { + error("ERROR: zip_stat_index failed for index %d\n", zindex); + goto leave; + } + + zfile = zip_fopen_index(za, zindex, 0); + if (zfile == NULL) { + error("ERROR: zip_fopen_index failed for index %d\n", zindex); + goto leave; + } + + size = zstat.size; + buffer = (unsigned char*) malloc(size+1); + if (buffer == NULL) { + error("ERROR: Out of memory\n"); + goto leave; + } + + if (zip_fread(zfile, buffer, size) != size) { + error("ERROR: zip_fread: failed\n"); + goto leave; + } + buffer[size] = '\0'; + + zip_fclose(zfile); + zfile = NULL; + + mbn = mbn_parse(buffer, size); + free(buffer); + buffer = NULL; + if (!mbn) { + error("ERROR: could not parse mbn file\n"); + goto leave; + } + + blob = NULL; + blob_size = 0; + plist_get_data_val(edbl, (char**)&blob, &blob_size); + if (!blob) { + error("ERROR: could not get eDBL-Blob data\n"); + goto leave; + } + + if (mbn_update_sig_blob(mbn, blob, (unsigned int)blob_size) != 0) { + error("ERROR: could not sign dbl.mbn\n"); + goto leave; + } + free(blob); + blob = NULL; + + mbnsize = mbn->size; + mbndata = (unsigned char*)malloc(mbnsize); + memcpy(mbndata, mbn->data, mbnsize); + mbn_free(mbn); + mbn = NULL; + + zs = zip_source_buffer(za, mbndata, mbnsize, 1); + if (!zs) { + error("ERROR: out of memory\n"); + goto leave; + } + + if (zip_replace(za, zindex, zs) == -1) { + error("ERROR: could not add signed dbl.mbn to archive\n"); + goto leave; + } + + // sign restoredbl.mbn + zindex = zip_name_locate(za, "restoredbl.mbn", 0); + if (zindex < 0) { + error("ERROR: can't locate 'restoredbl.mbn' in '%s'\n", bbfwtmp); + goto leave; + } + + zip_stat_init(&zstat); + if (zip_stat_index(za, zindex, 0, &zstat) != 0) { + error("ERROR: zip_stat_index failed for index %d\n", zindex); + goto leave; + } + + zfile = zip_fopen_index(za, zindex, 0); + if (zfile == NULL) { + error("ERROR: zip_fopen_index failed for index %d\n", zindex); + goto leave; + } + + size = zstat.size; + buffer = (unsigned char*) malloc(size+1); + if (buffer == NULL) { + error("ERROR: Out of memory\n"); + goto leave; + } + + if (zip_fread(zfile, buffer, size) != size) { + error("ERROR: zip_fread: failed\n"); + goto leave; + } + buffer[size] = '\0'; + + zip_fclose(zfile); + zfile = NULL; + + mbn = mbn_parse(buffer, size); + free(buffer); + buffer = NULL; + if (!mbn) { + error("ERROR: could not parse mbn file\n"); + goto leave; + } + + blob = NULL; + blob_size = 0; + plist_get_data_val(restoredbl, (char**)&blob, &blob_size); + if (!blob) { + error("ERROR: could not get RestoreDBL-Blob data\n"); + goto leave; + } + + if (mbn_update_sig_blob(mbn, blob, (unsigned int)blob_size) != 0) { + error("ERROR: could not sign restoredbl.mbn\n"); + goto leave; + } + free(blob); + blob = NULL; + + mbnsize = mbn->size; + mbndata = (unsigned char*)malloc(mbnsize); + memcpy(mbndata, mbn->data, mbnsize); + mbn_free(mbn); + mbn = NULL; + + zs = zip_source_buffer(za, mbndata, mbnsize, 1); + if (!zs) { + error("ERROR: out of memory\n"); + goto leave; + } + + if (zip_replace(za, zindex, zs) == -1) { + error("ERROR: could not add signed dbl.mbn to archive\n"); + goto leave; + } + + // add BBTicket as bbticket.der + blob = NULL; + blob_size = 0; + plist_get_data_val(bbticket, (char**)&blob, &blob_size); + if (!blob) { + error("ERROR: could not get BBTicket data\n"); + goto leave; + } + + zs = zip_source_buffer(za, blob, blob_size, 1); + if (!zs) { + error("ERROR: out of memory\n"); + goto leave; + } + + if (zip_add(za, "bbticket.der", zs) == -1) { + error("ERROR: could not add bbticket.der to archive\n"); + goto leave; + } + } + + // this will write out the modified zip + zip_close(za); + za = NULL; + zs = NULL; + + res = 0; + +leave: + if (mbn) { + mbn_free(mbn); + } + if (zfile) { + zip_fclose(zfile); + } + if (zs) { + zip_source_free(zs); + } + if (za) { + zip_unchange_all(za); + zip_close(za); + } + if (buffer) { + free(buffer); + } + if (blob) { + free(blob); + } + + return res; +} + +static int restore_handle_ice3_bbfw(const char* bbfwtmp, plist_t response, unsigned char* bb_nonce) +{ + int res = -1; // check for BBTicket in result plist_t bbticket = plist_dict_get_item(response, "BBTicket"); if (!bbticket || plist_get_node_type(bbticket) != PLIST_DATA) { error("ERROR: Could not find BBTicket in Baseband TSS response\n"); - free(response); return -1; } @@ -841,7 +1215,6 @@ int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_ plist_t rampsi = plist_access_path(response, 2, "BasebandFirmware", "RamPSI-Blob"); if (!rampsi || plist_get_node_type(rampsi) != PLIST_DATA) { error("ERROR: Could not find RamPSI-Blob in Baseband TSS response\n"); - free(response); return -1; } @@ -849,34 +1222,6 @@ int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_ plist_t flashpsi = plist_access_path(response, 2, "BasebandFirmware", "FlashPSI-Blob"); if (!flashpsi || plist_get_node_type(flashpsi) != PLIST_DATA) { error("ERROR: Could not find FlashPSI-Blob in Baseband TSS response\n"); - free(response); - return -1; - } - - // get baseband firmware file path from build identity - plist_t bbfw_path = plist_access_path(build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path"); - if (!bbfw_path || plist_get_node_type(bbfw_path) != PLIST_STRING) { - error("ERROR: Unable to get BasebandFirmware/Info/Path node\n"); - free(response); - return -1; - } - char* bbfwpath = NULL; - plist_get_string_val(bbfw_path, &bbfwpath); - if (!bbfwpath) { - error("ERROR: Unable to get baseband path\n"); - free(response); - return -1; - } - - // extract baseband firmware to temp file - char* bbfwtmp = tempnam(NULL, "bbfw_"); - if (!bbfwtmp) { - error("WARNING: Could not generate temporary filename, using bbfw.tmp\n"); - bbfwtmp = strdup("bbfw.tmp"); - } - if (ipsw_extract_to_file(client->ipsw, bbfwpath, bbfwtmp) != 0) { - error("ERROR: Unable to extract baseband firmware from ipsw\n"); - free(response); return -1; } @@ -1214,7 +1559,124 @@ int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_ za = NULL; zs = NULL; - buffer = NULL; + res = 0; + +leave: + if (fls) { + fls_free(fls); + } + if (zfile) { + zip_fclose(zfile); + } + if (zs) { + zip_source_free(zs); + } + if (za) { + zip_unchange_all(za); + zip_close(za); + } + if (buffer) { + free(buffer); + } + if (blob) { + free(blob); + } + + return res; +} + +int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) +{ + int res = -1; + uint64_t bb_cert_id = 0; + unsigned char* bb_snum = NULL; + uint64_t bb_snum_size = 0; + unsigned char* bb_nonce = NULL; + uint64_t bb_nonce_size = 0; + + // NOTE: this function is called twice! + + // setup request data + plist_t arguments = plist_dict_get_item(message, "Arguments"); + if (arguments && plist_get_node_type(arguments) == PLIST_DICT) { + plist_t bb_cert_id_node = plist_dict_get_item(arguments, "CertID"); + if (bb_cert_id_node && plist_get_node_type(bb_cert_id_node) == PLIST_UINT) { + plist_get_uint_val(bb_cert_id_node, &bb_cert_id); + } + plist_t bb_snum_node = plist_dict_get_item(arguments, "ChipSerialNo"); + if (bb_snum_node && plist_get_node_type(bb_snum_node) == PLIST_DATA) { + plist_get_data_val(bb_snum_node, (char**)&bb_snum, &bb_snum_size); + } + plist_t bb_nonce_node = plist_dict_get_item(arguments, "Nonce"); + if (bb_nonce_node && plist_get_node_type(bb_nonce_node) == PLIST_DATA) { + plist_get_data_val(bb_nonce_node, (char**)&bb_nonce, &bb_nonce_size); + } + } + + // create Baseband TSS request + plist_t request = tss_create_baseband_request(build_identity, client->ecid, bb_cert_id, bb_snum, bb_snum_size, bb_nonce, bb_nonce_size); + if (request == NULL) { + error("ERROR: Unable to create Baseand TSS request\n"); + return -1; + } + + // send Baseband TSS request + debug_plist(request); + info("Sending Baseband TSS request... "); + plist_t response = tss_send_request(request); + plist_free(request); + if (response == NULL) { + error("ERROR: Unable to fetch Baseband TSS\n"); + return -1; + } + debug_plist(response); + + // get baseband firmware file path from build identity + plist_t bbfw_path = plist_access_path(build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path"); + if (!bbfw_path || plist_get_node_type(bbfw_path) != PLIST_STRING) { + error("ERROR: Unable to get BasebandFirmware/Info/Path node\n"); + plist_free(response); + return -1; + } + char* bbfwpath = NULL; + plist_get_string_val(bbfw_path, &bbfwpath); + if (!bbfwpath) { + error("ERROR: Unable to get baseband path\n"); + plist_free(response); + return -1; + } + + // extract baseband firmware to temp file + char* bbfwtmp = tempnam(NULL, "bbfw_"); + if (!bbfwtmp) { + error("WARNING: Could not generate temporary filename, using bbfw.tmp\n"); + bbfwtmp = strdup("bbfw.tmp"); + } + if (ipsw_extract_to_file(client->ipsw, bbfwpath, bbfwtmp) != 0) { + error("ERROR: Unable to extract baseband firmware from ipsw\n"); + plist_free(response); + return -1; + } + + if (strncmp(bbfwpath, "Trek", 4) == 0) { + res = restore_handle_trek_bbfw(bbfwtmp, response, bb_nonce); + } else if (strncmp(bbfwpath, "ICE3", 4) == 0) { + res = restore_handle_ice3_bbfw(bbfwtmp, response, bb_nonce); + } else { + error("ERROR: unknown baseband firmware file format '%s'\n", bbfwpath); + remove(bbfwtmp); + free(bbfwtmp); + plist_free(response); + return -1; + } + + if (res != 0) { + goto leave; + } + + res = -1; + + unsigned char* buffer = NULL; size_t sz = 0; if (read_file(bbfwtmp, (void**)&buffer, &sz) < 0) { error("ERROR: could not read updated bbfw archive\n"); @@ -1241,25 +1703,9 @@ leave: if (dict) { plist_free(dict); } - if (fls) { - fls_free(fls); - } - if (zfile) { - zip_fclose(zfile); - } - if (zs) { - zip_source_free(zs); - } - if (za) { - zip_unchange_all(za); - zip_close(za); - } if (buffer) { free(buffer); } - if (blob) { - free(blob); - } if (bbfwtmp) { remove(bbfwtmp); free(bbfwtmp); -- cgit v1.1-32-gdbae