summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-23 12:40:06 -0400
committerGravatar Joshua Hill2010-05-23 12:40:06 -0400
commitdb663abb4d7fd66b5433d46d46b7cdeda22fccdc (patch)
tree9b98b849e2194f23c31ce79e0e5fec27aa3907a4
parentab1f7cb3c283b468235562b0b85db498b0a93766 (diff)
downloadidevicerestore-db663abb4d7fd66b5433d46d46b7cdeda22fccdc.tar.gz
idevicerestore-db663abb4d7fd66b5433d46d46b7cdeda22fccdc.tar.bz2
TSS stitching and loading of signed iBEC is now working, but launching from recovery mode causes libusb to fail unreferencing the device
-rw-r--r--src/idevicerestore.c37
-rw-r--r--src/img3.c236
-rw-r--r--src/img3.h7
3 files changed, 266 insertions, 14 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 0a5e7f1..1c8b24a 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -40,6 +40,7 @@
int idevicerestore_debug = 0;
void usage(int argc, char* argv[]);
+int write_file(const char* filename, char* data, int size);
int main(int argc, char* argv[]) {
int opt = 0;
@@ -302,7 +303,12 @@ int main(int argc, char* argv[]) {
ipsw_free_file(ibec);
img3_replace_signature(ibec_img3, ibec_blob);
- recovery_error = irecv_send_file(recovery, img3_get_data(ibec_img3));
+
+ int ibec_size = 0;
+ char* ibec_data = NULL;
+ img3_get_data(ibec_img3, &ibec_data, &ibec_size);
+ write_file("ibec.dfu", ibec_data, ibec_size);
+ recovery_error = irecv_send_buffer(recovery, ibec_data, ibec_size);
if(recovery_error != IRECV_E_SUCCESS) {
error("ERROR: Unable to send IMG3: %s\n", ibec_path);
irecv_close(recovery);
@@ -311,6 +317,16 @@ int main(int argc, char* argv[]) {
return -1;
}
+ recovery_error = irecv_send_command(recovery, "go");
+ if(recovery_error != IRECV_E_SUCCESS) {
+ error("ERROR: Unable to execute iBEC\n");
+ irecv_close(recovery);
+ img3_free(ibec_img3);
+ recovery = NULL;
+ return -1;
+ }
+
+ free(ibec_data);
irecv_close(recovery);
plist_free(tss_response);
return 0;
@@ -329,3 +345,22 @@ void usage(int argc, char* argv[]) {
printf("\n");
exit(1);
}
+
+int write_file(const char* filename, char* data, int size) {
+ debug("Writing data to %s\n", filename);
+ FILE* file = fopen(filename, "wb");
+ if (file == NULL) {
+ error("read_file: Unable to open file %s\n", filename);
+ return -1;
+ }
+
+ int bytes = fwrite(data, 1, size, file);
+ fclose(file);
+
+ if(bytes != size) {
+ error("ERROR: Unable to write entire file: %s: %d %d\n", filename, bytes, size);
+ return -1;
+ }
+
+ return size;
+}
diff --git a/src/img3.c b/src/img3.c
index cf2e91c..ec7bcbf 100644
--- a/src/img3.c
+++ b/src/img3.c
@@ -26,7 +26,7 @@
#include "img3.h"
#include "idevicerestore.h"
-img3_file* img3_parse_file(unsigned char* data, int size) {
+img3_file* img3_parse_file(char* data, int size) {
int data_offset = 0;
img3_header* header = (img3_header*) data;
if(header->signature != kImg3Container) {
@@ -107,7 +107,6 @@ img3_file* img3_parse_file(unsigned char* data, int size) {
case kKbagElement:
if(image->kbag1_element == NULL) {
image->kbag1_element = img3_parse_element(&data[data_offset]);
- image->kbag1_element = img3_parse_element(&data[data_offset]);
if(image->kbag1_element == NULL) {
error("ERROR: Unable to parse first KBAG element\n");
img3_free(image);
@@ -116,7 +115,6 @@ img3_file* img3_parse_file(unsigned char* data, int size) {
} else {
image->kbag2_element = img3_parse_element(&data[data_offset]);
- image->kbag2_element = img3_parse_element(&data[data_offset]);
if(image->kbag2_element == NULL) {
error("ERROR: Unable to parse second KBAG element\n");
img3_free(image);
@@ -167,9 +165,26 @@ img3_file* img3_parse_file(unsigned char* data, int size) {
return image;
}
-img3_element* img3_parse_element(char* element) {
- img3_element_header* element_header = (img3_element_header*) element;
- return 1;
+img3_element* img3_parse_element(char* data) {
+ img3_element_header* element_header = (img3_element_header*) data;
+ img3_element* element = (img3_element*) malloc(sizeof(img3_element));
+ if(element == NULL) {
+ error("ERROR: Unable to allocate memory for IMG3 element\n");
+ return NULL;
+ }
+ memset(element, '\0', sizeof(img3_element));
+
+ element->data = (char*) malloc(element_header->full_size);
+ if(element->data == NULL) {
+ error("ERROR: Unable to allocate memory for IMG3 element data\n");
+ free(element);
+ return NULL;
+ }
+ memcpy(element->data, data, element_header->full_size);
+ element->header = (img3_element_header*) element->data;
+ element->type = (img3_element_type) element->header->signature;
+
+ return element;
}
void img3_free(img3_file* image) {
@@ -178,14 +193,215 @@ void img3_free(img3_file* image) {
free(image->header);
}
+ if(image->type_element != NULL) {
+ img3_free_element(image->type_element);
+ image->type_element = NULL;
+ }
+
+ if(image->data_element != NULL) {
+ img3_free_element(image->data_element);
+ image->data_element = NULL;
+ }
+
+ if(image->vers_element != NULL) {
+ img3_free_element(image->vers_element);
+ image->vers_element = NULL;
+ }
+
+ if(image->sepo_element != NULL) {
+ img3_free_element(image->sepo_element);
+ image->sepo_element = NULL;
+ }
+
+ if(image->bord_element != NULL) {
+ img3_free_element(image->bord_element);
+ image->bord_element = NULL;
+ }
+
+ if(image->kbag1_element != NULL) {
+ img3_free_element(image->kbag1_element);
+ image->kbag1_element = NULL;
+ }
+
+ if(image->kbag2_element != NULL) {
+ img3_free_element(image->kbag2_element);
+ image->kbag2_element = NULL;
+ }
+
+ if(image->ecid_element != NULL) {
+ img3_free_element(image->ecid_element);
+ image->ecid_element = NULL;
+ }
+
+ if(image->shsh_element != NULL) {
+ img3_free_element(image->shsh_element);
+ image->shsh_element = NULL;
+ }
+
+ if(image->cert_element != NULL) {
+ img3_free_element(image->cert_element);
+ image->cert_element = NULL;
+ }
+
free(image);
+ image = NULL;
}
}
-void img3_replace_signature(img3_file* image, char* signature) {
- return;
+void img3_free_element(img3_element* element) {
+ if(element != NULL) {
+ if(element->data != NULL) {
+ free(element->data);
+ element->data = NULL;
+ }
+ free(element);
+ element = NULL;
+ }
}
-char* img3_get_data(img3_file* image) {
- return NULL;
+int img3_replace_signature(img3_file* image, char* signature) {
+ int offset = 0;
+ img3_element* ecid = img3_parse_element(&signature[offset]);
+ if(ecid == NULL || ecid->type != kEcidElement) {
+ error("ERROR: Unable to find ECID element in signature\n");
+ return -1;
+ }
+ offset += ecid->header->full_size;
+
+ img3_element* shsh = img3_parse_element(&signature[offset]);
+ if(shsh == NULL || shsh->type != kShshElement) {
+ error("ERROR: Unable to find SHSH element in signature\n");
+ return -1;
+ }
+ offset += shsh->header->full_size;
+
+ img3_element* cert = img3_parse_element(&signature[offset]);
+ if(cert == NULL || cert->type != kCertElement) {
+ error("ERROR: Unable to find CERT element in signature\n");
+ return -1;
+ }
+ offset += cert->header->full_size;
+
+ if(image->ecid_element != NULL) {
+ img3_free_element(image->ecid_element);
+ }
+ image->ecid_element = ecid;
+
+ if(image->shsh_element != NULL) {
+ img3_free_element(image->shsh_element);
+ }
+ image->shsh_element = shsh;
+
+ if(image->cert_element != NULL) {
+ img3_free_element(image->cert_element);
+ }
+ image->cert_element = cert;
+
+ return 0;
+}
+
+int img3_get_data(img3_file* image, char** pdata, int* psize) {
+ int offset = 0;
+ int size = sizeof(img3_header);
+
+ // Add up the size of the image first so we can allocate our memory
+ if(image->type_element != NULL) {
+ size += image->type_element->header->full_size;
+ }
+ if(image->data_element != NULL) {
+ size += image->data_element->header->full_size;
+ }
+ if(image->vers_element != NULL) {
+ size += image->vers_element->header->full_size;
+ }
+ if(image->sepo_element != NULL) {
+ size += image->sepo_element->header->full_size;
+ }
+ if(image->bord_element != NULL) {
+ size += image->bord_element->header->full_size;
+ }
+ if(image->kbag1_element != NULL) {
+ size += image->kbag1_element->header->full_size;
+ }
+ if(image->kbag2_element != NULL) {
+ size += image->kbag2_element->header->full_size;
+ }
+ if(image->ecid_element != NULL) {
+ size += image->ecid_element->header->full_size;
+ }
+ if(image->shsh_element != NULL) {
+ size += image->shsh_element->header->full_size;
+ }
+ if(image->cert_element != NULL) {
+ size += image->cert_element->header->full_size;
+ }
+
+ char* data = (char*) malloc(size);
+ if(data == NULL) {
+ error("ERROR: Unable to allocate memory for IMG3 data\n");
+ return -1;
+ }
+
+ // Add data to our new header (except shsh_offset)
+ img3_header* header = (img3_header*) data;
+ header->full_size = size;
+ header->signature = image->header->signature;
+ header->data_size = size - sizeof(img3_header);
+ header->image_type = image->header->image_type;
+ offset += sizeof(img3_header);
+
+ // Copy each section over to the new buffer
+ if(image->type_element != NULL) {
+ memcpy(&data[offset], image->type_element->data, image->type_element->header->full_size);
+ offset += image->type_element->header->full_size;
+ }
+ if(image->data_element != NULL) {
+ memcpy(&data[offset], image->data_element->data, image->data_element->header->full_size);
+ offset += image->data_element->header->full_size;
+ }
+ if(image->vers_element != NULL) {
+ memcpy(&data[offset], image->vers_element->data, image->vers_element->header->full_size);
+ offset += image->vers_element->header->full_size;
+ }
+ if(image->sepo_element != NULL) {
+ memcpy(&data[offset], image->sepo_element->data, image->sepo_element->header->full_size);
+ offset += image->sepo_element->header->full_size;
+ }
+ if(image->bord_element != NULL) {
+ memcpy(&data[offset], image->bord_element->data, image->bord_element->header->full_size);
+ offset += image->bord_element->header->full_size;
+ }
+ if(image->kbag1_element != NULL) {
+ memcpy(&data[offset], image->kbag1_element->data, image->kbag1_element->header->full_size);
+ offset += image->kbag1_element->header->full_size;
+ }
+ if(image->kbag2_element != NULL) {
+ memcpy(&data[offset], image->kbag2_element->data, image->kbag2_element->header->full_size);
+ offset += image->kbag2_element->header->full_size;
+ }
+ if(image->ecid_element != NULL) {
+ memcpy(&data[offset], image->ecid_element->data, image->ecid_element->header->full_size);
+ offset += image->ecid_element->header->full_size;
+ }
+ if(image->shsh_element != NULL) {
+ memcpy(&data[offset], image->shsh_element->data, image->shsh_element->header->full_size);
+ header->shsh_offset = offset - sizeof(img3_header);
+ offset += image->shsh_element->header->full_size;
+ }
+ if(image->cert_element != NULL) {
+ memcpy(&data[offset], image->cert_element->data, image->cert_element->header->full_size);
+ offset += image->cert_element->header->full_size;
+ }
+
+ if(offset != size) {
+ error("ERROR: Incorrectly sized image data\n");
+ free(data);
+ *pdata = 0;
+ *psize = 0;
+ return -1;
+ }
+
+ *pdata = data;
+ *psize = size;
+ return 0;
}
diff --git a/src/img3.h b/src/img3.h
index f2519f0..a19ae99 100644
--- a/src/img3.h
+++ b/src/img3.h
@@ -79,10 +79,11 @@ typedef struct {
img3_element* cert_element;
} img3_file;
-img3_file* img3_parse_file(unsigned char* data, int size);
+img3_file* img3_parse_file(char* data, int size);
img3_element* img3_parse_element(char* data);
-void img3_replace_signature(img3_file* image, char* signature);
+int img3_replace_signature(img3_file* image, char* signature);
void img3_free(img3_file* image);
-char* img3_get_data(img3_file* image);
+int img3_get_data(img3_file* image, char** pdata, int* psize);
+void img3_free_element(img3_element* element);
#endif