summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2012-07-17 16:40:31 +0200
committerGravatar Nikias Bassen2012-07-17 16:40:31 +0200
commit5232e5a5a421aacbb46a9f59282262a7832fe00b (patch)
tree0666b174bbb4daeeac7485b01c9f91277fc21fe9 /src
parent2a2004af685091c55e8008cc0a00084ade471cfe (diff)
downloadidevicerestore-5232e5a5a421aacbb46a9f59282262a7832fe00b.tar.gz
idevicerestore-5232e5a5a421aacbb46a9f59282262a7832fe00b.tar.bz2
restore: added .mbn file support and bbfw handling
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/mbn.c77
-rw-r--r--src/mbn.h52
-rw-r--r--src/restore.c606
4 files changed, 656 insertions, 81 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <stdint.h>
+
+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);