summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2012-07-17 01:15:10 +0200
committerGravatar Nikias Bassen2012-07-17 01:15:10 +0200
commit38de3e73bf0be64590af95cf785c3e5f2d62128a (patch)
tree03510834ad8e05f47e05e86adca3f33c116cd141 /src
parent28871d9f3f32afb78f0fbe029677756f24ba03cc (diff)
downloadidevicerestore-38de3e73bf0be64590af95cf785c3e5f2d62128a.tar.gz
idevicerestore-38de3e73bf0be64590af95cf785c3e5f2d62128a.tar.bz2
restore: implemented BasebandData request
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/fls.c339
-rw-r--r--src/fls.h85
-rw-r--r--src/restore.c529
4 files changed, 954 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 4d498a0..15d2552 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 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 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/fls.c b/src/fls.c
new file mode 100644
index 0000000..0970a8e
--- /dev/null
+++ b/src/fls.c
@@ -0,0 +1,339 @@
+/*
+ * fls.c
+ * support for .fls 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 "fls.h"
+#include "common.h"
+
+#ifndef offsetof
+#define offsetof(type, member) __builtin_offsetof (type, member)
+#endif
+
+static void fls_parse_elements(fls_file* fls)
+{
+ /* FIXME: the following code is not big endian safe */
+ if (!fls || !fls->data) {
+ return;
+ }
+ uint32_t offset = 0;
+ uint32_t max = fls->size;
+ fls->max_elements = 32;
+ fls->elements = (fls_element**)malloc(sizeof(fls_element*) * fls->max_elements);
+
+ fls_element* cur = NULL;
+ do {
+ void* p = fls->data + offset;
+ uint32_t hdrsize = 0;
+ cur = (fls_element*)p;
+ if ((offset + cur->size) > fls->size) {
+ break;
+ }
+ fls_element* ne;
+ switch (cur->type) {
+ case 0x0c:
+ {
+ hdrsize = offsetof(fls_0c_element, data);
+ fls_0c_element* xe = (fls_0c_element*)malloc(sizeof(fls_0c_element));
+ memset(xe, '\0', sizeof(fls_0c_element));
+ memcpy((void*)xe, p, hdrsize);
+ xe->data = (xe->size > hdrsize) ? xe->data = p + hdrsize : NULL;
+ ne = (fls_element*)xe;
+ fls->c_element = xe;
+ }
+ break;
+ case 0x10:
+ {
+ hdrsize = offsetof(fls_10_element, data);
+ fls_10_element* xe = (fls_10_element*)malloc(sizeof(fls_10_element));
+ memset(xe, '\0', sizeof(fls_10_element));
+ memcpy((void*)xe, p, hdrsize);
+ xe->data = (xe->size > hdrsize) ? xe->data = p + hdrsize : NULL;
+ ne = (fls_element*)xe;
+ }
+ break;
+ case 0x14:
+ {
+ hdrsize = offsetof(fls_14_element, data);
+ fls_14_element* xe = (fls_14_element*)malloc(sizeof(fls_14_element));
+ memset(xe, '\0', sizeof(fls_14_element));
+ memcpy((void*)xe, p, hdrsize);
+ xe->data = (xe->size > hdrsize) ? xe->data = p + hdrsize : NULL;
+ ne = (fls_element*)xe;
+ }
+ break;
+ default:
+ hdrsize = offsetof(fls_element, data);
+ ne = (fls_element*)malloc(sizeof(fls_element));
+ memset(ne, '\0', sizeof(fls_element));
+ ne->type = cur->type;
+ ne->size = cur->size;
+ ne->data = (ne->size > hdrsize) ? ne->data = p + hdrsize : NULL;
+ break;
+ }
+ if ((fls->num_elements + 1) > fls->max_elements) {
+ fls->max_elements += 10;
+ fls->elements = (fls_element**)realloc(fls->elements, sizeof(fls_element*) * fls->max_elements);
+ }
+ fls->elements[fls->num_elements++] = ne;
+ offset += cur->size;
+ } while (offset < fls->size);
+ if (offset != fls->size) {
+ error("ERROR: %s: error parsing elements\n", __func__);
+ return;
+ }
+}
+
+fls_file* fls_parse(unsigned char* data, unsigned int size)
+{
+ fls_file* fls = (fls_file*)malloc(sizeof(fls_file));
+ if (!fls) {
+ return NULL;
+ }
+ memset(fls, '\0', sizeof(fls_file));
+ fls->data = malloc(size);
+ fls->size = size;
+ memcpy(fls->data, data, size);
+ fls_parse_elements(fls);
+ return fls;
+}
+
+void fls_free(fls_file* fls)
+{
+ if (fls) {
+ if (fls->num_elements > 0) {
+ int i;
+ for (i = fls->num_elements-1; i >=0; i--) {
+ free(fls->elements[i]);
+ }
+ free(fls->elements);
+ }
+ if (fls->data) {
+ free(fls->data);
+ }
+ free(fls);
+ }
+}
+
+int fls_update_sig_blob(fls_file* fls, const unsigned char* sigdata, unsigned int siglen)
+{
+ /* FIXME: the code in this function is not big endian safe */
+ if (!fls || !fls->num_elements) {
+ error("ERROR: %s: no data\n", __func__);
+ return -1;
+ }
+ if (!fls->c_element) {
+ error("ERROR: %s: no fls_0c_element in fls data\n", __func__);
+ return -1;
+ }
+
+ uint32_t datasize = *(uint32_t*)(fls->c_element->data + 0x10);
+ if (datasize != fls->c_element->data_size) {
+ error("ERROR: %s: data size mismatch (0x%x != 0x%x)\n", __func__, datasize, fls->c_element->data_size);
+ return -1;
+ }
+ uint32_t sigoffset = *(uint32_t*)(fls->c_element->data + 0x14);
+ if (sigoffset > datasize) {
+ error("ERROR: %s: signature offset greater than data size (0x%x > 0x%x)\n", __func__, sigoffset, datasize);
+ return -1;
+ }
+
+ uint32_t oldsiglen = datasize - sigoffset;
+ uint32_t newsize = fls->size - oldsiglen + siglen;
+
+ int i;
+ uint32_t offset = 0;
+ void* newdata = malloc(newsize);
+ if (!newdata) {
+ error("ERROR: %s: out of memory\n", __func__);
+ return -1;
+ }
+ uint32_t hdrsize = 0;
+ uint32_t firstpartlen = 0;
+ for (i = 0; i < fls->num_elements; i++) {
+ switch (fls->elements[i]->type) {
+ case 0x0c:
+ hdrsize = offsetof(fls_0c_element, data);
+ // update offset
+ ((fls_0c_element*)fls->elements[i])->offset = offset+hdrsize;
+ // copy first part of data
+ firstpartlen = fls->elements[i]->size - hdrsize - oldsiglen;
+ memcpy(newdata+offset+hdrsize, ((fls_0c_element*)fls->elements[i])->data, firstpartlen);
+ // copy new signature data
+ memcpy(newdata+offset+hdrsize+firstpartlen, sigdata, siglen);
+ ((fls_0c_element*)fls->elements[i])->data = newdata+offset+hdrsize;
+ fls->elements[i]->size -= oldsiglen;
+ fls->elements[i]->size += siglen;
+ ((fls_0c_element*)fls->elements[i])->data_size -= oldsiglen;
+ ((fls_0c_element*)fls->elements[i])->data_size += siglen;
+ memcpy(newdata+offset+hdrsize+0x10, &(((fls_0c_element*)fls->elements[i])->data_size), 4);
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ break;
+ case 0x10:
+ hdrsize = offsetof(fls_10_element, data);
+ // update offset
+ ((fls_10_element*)fls->elements[i])->offset = offset+hdrsize;
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ // copy data
+ if (fls->elements[i]->size > hdrsize) {
+ memcpy(newdata+offset+hdrsize, ((fls_10_element*)fls->elements[i])->data, fls->elements[i]->size - hdrsize);
+ ((fls_10_element*)fls->elements[i])->data = newdata+offset+hdrsize;
+ } else {
+ ((fls_10_element*)fls->elements[i])->data = NULL;
+ }
+ break;
+ case 0x14:
+ hdrsize = offsetof(fls_14_element, data);
+ // update offset
+ ((fls_14_element*)fls->elements[i])->offset = offset+hdrsize;
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ // copy data
+ if (fls->elements[i]->size > hdrsize) {
+ memcpy(newdata+offset+hdrsize, ((fls_14_element*)fls->elements[i])->data, fls->elements[i]->size - hdrsize);
+ ((fls_14_element*)fls->elements[i])->data = newdata+offset+hdrsize;
+ } else {
+ ((fls_14_element*)fls->elements[i])->data = NULL;
+ }
+ break;
+ default:
+ hdrsize = offsetof(fls_element, data);
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ // copy data
+ if (fls->elements[i]->size > hdrsize) {
+ memcpy(newdata+offset+hdrsize, fls->elements[i]->data, fls->elements[i]->size - hdrsize);
+ fls->elements[i]->data = newdata+offset+hdrsize;
+ } else {
+ fls->elements[i]->data = NULL;
+ }
+ break;
+ }
+ offset += fls->elements[i]->size;
+ }
+ if (fls->data) {
+ free(fls->data);
+ }
+ fls->data = newdata;
+ fls->size = newsize;
+
+ return 0;
+}
+
+int fls_insert_ticket(fls_file* fls, const unsigned char* data, unsigned int size)
+{
+ /* FIXME: the code in this function is not big endian safe */
+ if (!fls || !fls->num_elements) {
+ error("ERROR: %s: no data\n", __func__);
+ return -1;
+ }
+ if (!fls->c_element) {
+ error("ERROR: %s: no fls_0c_element in fls data\n", __func__);
+ return -1;
+ }
+
+ uint32_t padding = 0;
+ if (size%4 != 0) {
+ padding = 4-(size%4);
+ }
+ uint32_t newsize = fls->size + size + padding;
+ int i;
+ uint32_t offset = 0;
+ void* newdata = malloc(newsize);
+ if (!newdata) {
+ error("ERROR: %s: out of memory\n", __func__);
+ return -1;
+ }
+ uint32_t hdrsize = 0;
+ for (i = 0; i < fls->num_elements; i++) {
+ switch (fls->elements[i]->type) {
+ case 0x0c:
+ hdrsize = offsetof(fls_0c_element, data);
+ // update offset
+ ((fls_0c_element*)fls->elements[i])->offset = offset+hdrsize;
+ // copy ticket data
+ memcpy(newdata+offset+hdrsize, data, size);
+ if (padding > 0) {
+ // padding
+ memset(newdata+offset+hdrsize+size, '\xFF', padding);
+ }
+ // copy remaining data
+ memcpy(newdata+offset+hdrsize+size+padding, ((fls_0c_element*)fls->elements[i])->data, fls->elements[i]->size);
+ ((fls_0c_element*)fls->elements[i])->data = newdata+offset+hdrsize;
+ fls->elements[i]->size += (size + padding);
+ ((fls_0c_element*)fls->elements[i])->data_size += (size + padding);
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ break;
+ case 0x10:
+ hdrsize = offsetof(fls_10_element, data);
+ // update offset
+ ((fls_10_element*)fls->elements[i])->offset = offset+hdrsize;
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ // copy data
+ if (fls->elements[i]->size > hdrsize) {
+ memcpy(newdata+offset+hdrsize, ((fls_10_element*)fls->elements[i])->data, fls->elements[i]->size - hdrsize);
+ ((fls_10_element*)fls->elements[i])->data = newdata+offset+hdrsize;
+ } else {
+ ((fls_10_element*)fls->elements[i])->data = NULL;
+ }
+ break;
+ case 0x14:
+ hdrsize = offsetof(fls_14_element, data);
+ // update offset
+ ((fls_14_element*)fls->elements[i])->offset = offset+hdrsize;
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ // copy data
+ if (fls->elements[i]->size > hdrsize) {
+ memcpy(newdata+offset+hdrsize, ((fls_14_element*)fls->elements[i])->data, fls->elements[i]->size - hdrsize);
+ ((fls_14_element*)fls->elements[i])->data = newdata+offset+hdrsize;
+ } else {
+ ((fls_14_element*)fls->elements[i])->data = NULL;
+ }
+ break;
+ default:
+ hdrsize = offsetof(fls_element, data);
+ // copy header
+ memcpy(newdata+offset, fls->elements[i], hdrsize);
+ // copy data
+ if (fls->elements[i]->size > hdrsize) {
+ memcpy(newdata+offset+hdrsize, fls->elements[i]->data, fls->elements[i]->size - hdrsize);
+ fls->elements[i]->data = newdata+offset+hdrsize;
+ } else {
+ fls->elements[i]->data = NULL;
+ }
+ break;
+ }
+ offset += fls->elements[i]->size;
+ }
+ if (fls->data) {
+ free(fls->data);
+ }
+ fls->data = newdata;
+ fls->size = newsize;
+
+ return 0;
+}
+
diff --git a/src/fls.h b/src/fls.h
new file mode 100644
index 0000000..57b3869
--- /dev/null
+++ b/src/fls.h
@@ -0,0 +1,85 @@
+/*
+ * fls.h
+ * support for .fls 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 FLS_H
+#define FLS_H
+
+#include <stdint.h>
+
+struct _fls_element {
+ uint32_t type;
+ uint32_t size;
+ uint32_t empty;
+ const unsigned char* data;
+} __attribute__((packed));
+typedef struct _fls_element fls_element;
+
+struct _fls_0c_element {
+ uint32_t type;
+ uint32_t size;
+ uint32_t empty;
+ uint32_t off_0x0c;
+ uint32_t off_0x10;
+ uint32_t off_0x14;
+ uint32_t off_0x18;
+ uint32_t data_size; // size without header
+ uint32_t off_0x20;
+ uint32_t offset; // absolute offset of data in file
+ const unsigned char* data; // data+0x14 contains offset to sig blob
+} __attribute__((packed));
+typedef struct _fls_0c_element fls_0c_element;
+
+struct _fls_10_element {
+ uint32_t type;
+ uint32_t size;
+ uint32_t empty;
+ uint32_t data_size; // size without header
+ uint32_t off_0x10;
+ uint32_t offset;
+ const unsigned char* data;
+} __attribute__((packed));
+typedef struct _fls_10_element fls_10_element;
+
+struct _fls_14_element {
+ uint32_t type;
+ uint32_t size;
+ uint32_t empty;
+ uint32_t data_size; // size without header
+ uint32_t off_0x10;
+ uint32_t offset;
+ const unsigned char* data;
+} __attribute__((packed));
+typedef struct _fls_14_element fls_14_element;
+
+typedef struct {
+ unsigned int num_elements;
+ unsigned int max_elements;
+ fls_element** elements;
+ const fls_0c_element* c_element;
+ void* data;
+ uint32_t size;
+} fls_file;
+
+fls_file* fls_parse(unsigned char* data, unsigned int size);
+void fls_free(fls_file* fls);
+int fls_update_sig_blob(fls_file* fls, const unsigned char* data, unsigned int size);
+int fls_insert_ticket(fls_file* fls, const unsigned char* data, unsigned int size);
+
+#endif
diff --git a/src/restore.c b/src/restore.c
index e96fed9..5da614f 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -23,8 +23,10 @@
#include <stdlib.h>
#include <string.h>
#include <libimobiledevice/restore.h>
+#include <zip.h>
#include "asr.h"
+#include "fls.h"
#include "tss.h"
#include "common.h"
#include "restore.h"
@@ -510,6 +512,35 @@ int restore_handle_status_msg(restored_client_t client, plist_t msg) {
return result;
}
+int restore_handle_bb_update_status_msg(restored_client_t client, plist_t msg)
+{
+ int result = -1;
+ plist_t node = plist_dict_get_item(msg, "Accepted");
+ uint8_t accepted = 0;
+ plist_get_bool_val(node, &accepted);
+ debug_plist(msg);
+
+ if (!accepted) {
+ error("ERROR: device didn't accept BasebandData\n");
+ return result;
+ }
+
+ uint8_t done = 0;
+ node = plist_access_path(msg, 2, "Output", "done");
+ if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
+ plist_get_bool_val(node, &done);
+ }
+
+ if (done) {
+ info("Updating Baseband completed.\n");
+ } else {
+ info("Updating Baseband in progress...\n");
+ }
+ result = 0;
+
+ return result;
+}
+
int restore_send_filesystem(idevice_t device, const char* filesystem) {
int i = 0;
FILE* file = NULL;
@@ -737,6 +768,492 @@ 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)
+{
+ 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);
+ }
+ }
+
+ // 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);
+
+ // 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;
+ }
+
+ // check for RamPSI-Blob in result
+ 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;
+ }
+
+ // check for FlashPSI-Blob in result
+ 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;
+ }
+
+ unsigned char* buffer = NULL;
+ unsigned char* blob = NULL;
+ unsigned char* flsdata = NULL;
+ off_t flssize = 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;
+ fls_file* fls = NULL;
+
+ 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) {
+ // just sign psi_ram.fls
+ zindex = zip_name_locate(za, "psi_ram.fls", 0);
+ if (zindex < 0) {
+ error("ERROR: can't locate 'psi_ram.fls' 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;
+
+ fls = fls_parse(buffer, size);
+ free(buffer);
+ buffer = NULL;
+ if (!fls) {
+ error("ERROR: could not parse fls file\n");
+ goto leave;
+ }
+
+ blob = NULL;
+ blob_size = 0;
+ plist_get_data_val(rampsi, (char**)&blob, &blob_size);
+ if (!blob) {
+ error("ERROR: could not get RamPSI-Blob data\n");
+ goto leave;
+ }
+
+ if (fls_update_sig_blob(fls, blob, (unsigned int)blob_size) != 0) {
+ error("ERROR: could not sign psi_ram.fls\n");
+ goto leave;
+ }
+ free(blob);
+ blob = NULL;
+
+ // remove all files from zip
+ int i;
+ int numf = zip_get_num_files(za);
+ for (i = 0; i < numf; i++) {
+ zip_delete(za, i);
+ }
+
+ flssize = fls->size;
+ flsdata = (unsigned char*)malloc(flssize);
+ memcpy(flsdata, fls->data, flssize);
+ fls_free(fls);
+ fls = NULL;
+
+ zs = zip_source_buffer(za, flsdata, flssize, 1);
+ if (!zs) {
+ error("ERROR: out of memory\n");
+ goto leave;
+ }
+
+ if (zip_add(za, "psi_ram.fls", zs) == -1) {
+ error("ERROR: could not add signed psi_ram.fls to archive\n");
+ goto leave;
+ }
+ } else {
+ // sign psi_ram.fls
+ zindex = zip_name_locate(za, "psi_ram.fls", 0);
+ if (zindex < 0) {
+ error("ERROR: can't locate 'psi_ram.fls' 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;
+
+ fls = fls_parse(buffer, size);
+ free(buffer);
+ buffer = NULL;
+ if (!fls) {
+ error("ERROR: could not parse fls file\n");
+ goto leave;
+ }
+
+ blob = NULL;
+ blob_size = 0;
+ plist_get_data_val(rampsi, (char**)&blob, &blob_size);
+ if (!blob) {
+ error("ERROR: could not get RamPSI-Blob data\n");
+ goto leave;
+ }
+
+ if (fls_update_sig_blob(fls, blob, (unsigned int)blob_size) != 0) {
+ error("ERROR: could not sign psi_ram.fls\n");
+ goto leave;
+ }
+ free(blob);
+ blob = NULL;
+
+ flssize = fls->size;
+ flsdata = (unsigned char*)malloc(flssize);
+ memcpy(flsdata, fls->data, flssize);
+ fls_free(fls);
+ fls = NULL;
+
+ zs = zip_source_buffer(za, flsdata, flssize, 1);
+ if (!zs) {
+ error("ERROR: out of memory\n");
+ goto leave;
+ }
+
+ if (zip_replace(za, zindex, zs) == -1) {
+ error("ERROR: could not add signed psi_ram.fls to archive\n");
+ goto leave;
+ }
+
+ // sign psi_flash.fls
+ zindex = zip_name_locate(za, "psi_flash.fls", 0);
+ if (zindex < 0) {
+ error("ERROR: can't locate 'psi_flash.fls' 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;
+
+ fls = fls_parse(buffer, size);
+ free(buffer);
+ buffer = NULL;
+ if (!fls) {
+ error("ERROR: could not parse fls file\n");
+ goto leave;
+ }
+
+ blob = NULL;
+ blob_size = 0;
+ plist_get_data_val(flashpsi, (char**)&blob, &blob_size);
+ if (!blob) {
+ error("ERROR: could not get FlashPSI-Blob data\n");
+ goto leave;
+ }
+
+ if (fls_update_sig_blob(fls, blob, (unsigned int)blob_size) != 0) {
+ error("ERROR: could not sign psi_flash.fls\n");
+ goto leave;
+ }
+ free(blob);
+ blob = NULL;
+
+ flssize = fls->size;
+ flsdata = (unsigned char*)malloc(flssize);
+ memcpy(flsdata, fls->data, flssize);
+ fls_free(fls);
+ fls = NULL;
+
+ zs = zip_source_buffer(za, flsdata, flssize, 1);
+ if (!zs) {
+ error("ERROR: out of memory\n");
+ goto leave;
+ }
+
+ if (zip_replace(za, zindex, zs) == -1) {
+ error("ERROR: could not add signed psi_flash.fls to archive\n");
+ goto leave;
+ }
+
+ // add ticket to ebl.fls
+ zindex = zip_name_locate(za, "ebl.fls", 0);
+ if (zindex < 0) {
+ error("ERROR: can't locate 'ebl.fls' 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;
+
+ fls = fls_parse(buffer, size);
+ free(buffer);
+ buffer = NULL;
+ if (!fls) {
+ error("ERROR: could not parse fls file\n");
+ goto leave;
+ }
+
+ 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;
+ }
+
+ if (fls_insert_ticket(fls, blob, (unsigned int)blob_size) != 0) {
+ error("ERROR: could not insert BBTicket to ebl.fls\n");
+ goto leave;
+ }
+ free(blob);
+ blob = NULL;
+
+ flssize = fls->size;
+ flsdata = (unsigned char*)malloc(flssize);
+ memcpy(flsdata, fls->data, flssize);
+ fls_free(fls);
+ fls = NULL;
+
+ zs = zip_source_buffer(za, flsdata, flssize, 1);
+ if (!zs) {
+ error("ERROR: out of memory\n");
+ goto leave;
+ }
+
+ if (zip_replace(za, zindex, zs) == -1) {
+ error("ERROR: could not add ticketed ebl.fls to archive\n");
+ goto leave;
+ }
+ }
+
+ // this will write out the modified zip
+ zip_close(za);
+ za = NULL;
+ zs = NULL;
+
+ buffer = NULL;
+ size_t sz = 0;
+ if (read_file(bbfwtmp, (void**)&buffer, &sz) < 0) {
+ error("ERROR: could not read updated bbfw archive\n");
+ goto leave;
+ }
+
+ // send file
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "BasebandData", plist_new_data(buffer, (uint64_t)sz));
+ free(buffer);
+ buffer = NULL;
+
+ if (restored_send(restore, dict) != RESTORE_E_SUCCESS) {
+ error("ERROR: Unable to send BasebandData data\n");
+ goto leave;
+ }
+
+ plist_free(dict);
+ dict = NULL;
+
+ res = 0;
+
+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);
+ }
+ if (response) {
+ free(response);
+ }
+
+ return res;
+}
+
int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity, const char* filesystem) {
char* type = NULL;
plist_t node = NULL;
@@ -781,6 +1298,13 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
info("Not sending NORData... Quitting...\n");
client->flags |= FLAG_QUIT;
}
+ }
+
+ else if (!strcmp(type, "BasebandData")) {
+ if(restore_send_baseband_data(restore, client, build_identity, message) < 0) {
+ error("ERROR: Unable to send baseband data\n");
+ return -1;
+ }
} else {
// Unknown DataType!!
@@ -929,6 +1453,11 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
}
}
+ // baseband update message
+ else if (!strcmp(type, "BBUpdateStatusMsg")) {
+ error = restore_handle_bb_update_status_msg(restore, message);
+ }
+
// there might be some other message types i'm not aware of, but I think
// at least the "previous error logs" messages usually end up here
else {