summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2013-11-19 22:04:30 +0100
committerGravatar Nikias Bassen2013-11-19 22:04:30 +0100
commit669ac822c564c5a6358daa7a49f6d0b336591558 (patch)
treed43ba8b1d4bb3c7008b483fc8f1896f41797fdb1
parent26f34f031287b232b45df00e566c356fb95c399a (diff)
downloadidevicerestore-669ac822c564c5a6358daa7a49f6d0b336591558.tar.gz
idevicerestore-669ac822c564c5a6358daa7a49f6d0b336591558.tar.bz2
tss: Refactor TSS handlers for Image4 support and flexibility
-rw-r--r--src/dfu.c6
-rw-r--r--src/idevicerestore.c43
-rw-r--r--src/idevicerestore.h2
-rw-r--r--src/recovery.c4
-rw-r--r--src/restore.c23
-rw-r--r--src/tss.c510
-rw-r--r--src/tss.h30
7 files changed, 403 insertions, 215 deletions
diff --git a/src/dfu.c b/src/dfu.c
index 37fa2d4..5fdbfd5 100644
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -166,7 +166,7 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
int flag = 1;
if (client->tss) {
- if (tss_get_entry_path(client->tss, component, &path) < 0) {
+ if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) {
debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component);
}
}
@@ -188,7 +188,7 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
if (!(client->flags & FLAG_CUSTOM) && (strcmp(component, "iBEC") == 0)) {
unsigned char* ticket = NULL;
unsigned int tsize = 0;
- if (tss_get_ticket(client->tss, &ticket, &tsize) < 0) {
+ if (tss_response_get_ap_ticket(client->tss, &ticket, &tsize) < 0) {
error("ERROR: Unable to get ApTicket from TSS request\n");
return -1;
}
@@ -379,7 +379,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
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, build_identity, &client->tss) < 0) {
+ if (get_tss_response(client, build_identity, &client->tss) < 0) {
error("ERROR: Unable to get SHSH blobs for this device\n");
return -1;
}
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 1ad62a9..a09b841 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -582,7 +582,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
}
- if (get_shsh_blobs(client, build_identity, &client->tss) < 0) {
+ if (get_tss_response(client, build_identity, &client->tss) < 0) {
error("ERROR: Unable to get SHSH blobs for this device\n");
return -1;
}
@@ -836,7 +836,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
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, build_identity, &client->tss) < 0) {
+ if (get_tss_response(client, build_identity, &client->tss) < 0) {
error("ERROR: Unable to get SHSH blobs for this device\n");
if (delete_fs && filesystem)
unlink(filesystem);
@@ -1339,7 +1339,7 @@ plist_t build_manifest_get_build_identity(plist_t build_manifest, uint32_t ident
return plist_copy(build_identity);
}
-int get_shsh_blobs(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss) {
+int get_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss) {
plist_t request = NULL;
plist_t response = NULL;
*tss = NULL;
@@ -1406,23 +1406,52 @@ int get_shsh_blobs(struct idevicerestore_client_t* client, plist_t build_identit
info("Trying to fetch new SHSH blob\n");
}
- request = tss_create_request(build_identity, client->ecid, client->nonce, client->nonce_size);
+ /* populate parameters */
+ plist_t parameters = plist_new_dict();
+ plist_dict_insert_item(parameters, "ApECID", plist_new_uint(client->ecid));
+ plist_dict_insert_item(parameters, "ApNonce", plist_new_data(client->nonce, client->nonce_size));
+ plist_dict_insert_item(parameters, "ApProductionMode", plist_new_bool(1));
+
+ /* create basic request */
+ request = tss_request_new(NULL);
if (request == NULL) {
error("ERROR: Unable to create TSS request\n");
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add tags from manifest */
+ if (tss_request_add_ap_tags_from_manifest(request, build_identity, NULL) < 0) {
+ error("ERROR: Unable to create TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
return -1;
}
- response = tss_send_request(request, client->tss_url);
+ /* add personalized parameters */
+ if (tss_request_add_ap_img3_tags(request, parameters) < 0) {
+ error("ERROR: Unable to create TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ };
+
+ /* send request and grab response */
+ response = tss_request_send(request, client->tss_url);
if (response == NULL) {
info("ERROR: Unable to send TSS request\n");
plist_free(request);
+ plist_free(parameters);
return -1;
}
info("Received SHSH blobs\n");
plist_free(request);
+ plist_free(parameters);
+
*tss = response;
+
return 0;
}
@@ -1492,11 +1521,11 @@ int ipsw_get_component_by_path(const char* ipsw, plist_t tss, const char* compon
if (tss) {
/* try to get blob for current component from tss response */
if (component) {
- if (tss_get_blob_by_name(tss, component, &component_blob) < 0) {
+ if (tss_response_get_blob_by_entry(tss, component, &component_blob) < 0) {
debug("NOTE: No SHSH blob found for TSS entry %s from component %s\n", component_name, component);
}
} else {
- if (tss_get_blob_by_path(tss, path, &component_blob) < 0) {
+ if (tss_response_get_blob_by_path(tss, path, &component_blob) < 0) {
debug("NOTE: No SHSH blob found for TSS entry %s from path %s\n", component_name, path);
}
}
diff --git a/src/idevicerestore.h b/src/idevicerestore.h
index 742d7f9..148c78d 100644
--- a/src/idevicerestore.h
+++ b/src/idevicerestore.h
@@ -78,7 +78,7 @@ int get_ecid(struct idevicerestore_client_t* client, uint64_t* ecid);
int is_image4_supported(struct idevicerestore_client_t* client);
int get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size);
int get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size);
-int get_shsh_blobs(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss);
+int get_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss);
void fixup_tss(plist_t tss);
int build_manifest_get_identity_count(plist_t build_manifest);
int build_manifest_check_compatibility(plist_t build_manifest, const char* product);
diff --git a/src/recovery.c b/src/recovery.c
index 9221dda..518b0b8 100644
--- a/src/recovery.c
+++ b/src/recovery.c
@@ -236,7 +236,7 @@ int recovery_send_ticket(struct idevicerestore_client_t* client)
unsigned char* data = NULL;
uint32_t size = 0;
- if (tss_get_ticket(client->tss, &data, &size) < 0) {
+ if (tss_response_get_ap_ticket(client->tss, &data, &size) < 0) {
error("ERROR: Unable to get ApTicket from TSS request\n");
return -1;
}
@@ -267,7 +267,7 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
irecv_error_t err = 0;
if (client->tss) {
- if (tss_get_entry_path(client->tss, component, &path) < 0) {
+ if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) {
debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component);
}
}
diff --git a/src/restore.c b/src/restore.c
index 607f95f..bb5b352 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -737,7 +737,7 @@ int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_cl
return -1;
}
- if (!(client->flags & FLAG_CUSTOM) && (tss_get_ticket(client->tss, &data, &len) < 0)) {
+ if (!(client->flags & FLAG_CUSTOM) && (tss_response_get_ap_ticket(client->tss, &data, &len) < 0)) {
error("ERROR: Unable to get ticket from TSS\n");
return -1;
}
@@ -774,7 +774,7 @@ int restore_send_kernelcache(restored_client_t restore, struct idevicerestore_cl
info("About to send KernelCache...\n");
if (client->tss) {
- if (tss_get_entry_path(client->tss, "KernelCache", &path) < 0) {
+ if (tss_response_get_path_by_entry(client->tss, "KernelCache", &path) < 0) {
debug("NOTE: No path for component KernelCache in TSS, will fetch from build_identity\n");
}
}
@@ -830,7 +830,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
info("About to send NORData...\n");
if (client->tss) {
- if (tss_get_entry_path(client->tss, "LLB", &llb_path) < 0) {
+ if (tss_response_get_path_by_entry(client->tss, "LLB", &llb_path) < 0) {
debug("NOTE: Could not get LLB path from TSS data, will fetch from build identity\n");
}
}
@@ -1319,8 +1319,19 @@ int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_
}
if ((bb_nonce == NULL) || (client->restore->bbtss == NULL)) {
- // 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);
+ /* populate parameters */
+ plist_t parameters = plist_new_dict();
+ plist_dict_insert_item(parameters, "ApECID", plist_new_uint(client->ecid));
+ plist_dict_insert_item(parameters, "BbNonce", plist_new_data(bb_nonce, bb_nonce_size));
+ plist_dict_insert_item(parameters, "BbChipID", plist_new_uint(bb_chip_id));
+ plist_dict_insert_item(parameters, "BbGoldCertId", plist_new_uint(bb_cert_id));
+ plist_dict_insert_item(parameters, "BbSNUM", plist_new_data(bb_snum, bb_snum_size));
+
+ /* create baseband request */
+ plist_t request = tss_request_new(NULL);
+ tss_request_add_baseband_tags_from_manifest(request, build_identity, NULL);
+ tss_request_add_baseband_tags(request, parameters);
+
if (request == NULL) {
error("ERROR: Unable to create Baseand TSS request\n");
return -1;
@@ -1331,7 +1342,7 @@ int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_
debug_plist(request);
info("Sending Baseband TSS request...\n");
- response = tss_send_request(request, client->tss_url);
+ response = tss_request_send(request, client->tss_url);
plist_free(request);
if (response == NULL) {
error("ERROR: Unable to fetch Baseband TSS\n");
diff --git a/src/tss.c b/src/tss.c
index 8a04868..04f0d6d 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -33,6 +33,7 @@
#include "common.h"
#include "idevicerestore.h"
+#define TSS_CLIENT_VERSION_STRING "libauthinstall-293.1.16"
#define ECID_STRSIZE 0x20
typedef struct {
@@ -40,92 +41,262 @@ typedef struct {
char* content;
} tss_response;
-plist_t tss_create_request(plist_t build_identity, uint64_t ecid, unsigned char* nonce, int nonce_size) {
- uint64_t unique_build_size = 0;
- char* unique_build_data = NULL;
- plist_t unique_build_node = plist_dict_get_item(build_identity, "UniqueBuildID");
- if (!unique_build_node || plist_get_node_type(unique_build_node) != PLIST_DATA) {
- error("ERROR: Unable to find UniqueBuildID node\n");
- return NULL;
- }
- plist_get_data_val(unique_build_node, &unique_build_data, &unique_build_size);
-
- int chip_id = 0;
- char* chip_id_string = NULL;
- plist_t chip_id_node = plist_dict_get_item(build_identity, "ApChipID");
- if (!chip_id_node || plist_get_node_type(chip_id_node) != PLIST_STRING) {
- error("ERROR: Unable to find ApChipID node\n");
- return NULL;
- }
- plist_get_string_val(chip_id_node, &chip_id_string);
- sscanf(chip_id_string, "%x", &chip_id);
-
- int board_id = 0;
- char* board_id_string = NULL;
- plist_t board_id_node = plist_dict_get_item(build_identity, "ApBoardID");
- if (!board_id_node || plist_get_node_type(board_id_node) != PLIST_STRING) {
- error("ERROR: Unable to find ApBoardID node\n");
- return NULL;
- }
- plist_get_string_val(board_id_node, &board_id_string);
- sscanf(board_id_string, "%x", &board_id);
-
- int security_domain = 0;
- char* security_domain_string = NULL;
- plist_t security_domain_node = plist_dict_get_item(build_identity, "ApSecurityDomain");
- if (!security_domain_node || plist_get_node_type(security_domain_node) != PLIST_STRING) {
- error("ERROR: Unable to find ApSecurityDomain node\n");
- return NULL;
- }
- plist_get_string_val(security_domain_node, &security_domain_string);
- sscanf(security_domain_string, "%x", &security_domain);
-
- char ecid_string[ECID_STRSIZE];
+char* ecid_to_string(uint64_t ecid) {
+ char* ecid_string = malloc(ECID_STRSIZE);
memset(ecid_string, '\0', ECID_STRSIZE);
if (ecid == 0) {
- error("ERROR: Unable to get ECID\n");
+ error("ERROR: Invalid ECID passed.\n");
return NULL;
}
snprintf(ecid_string, ECID_STRSIZE, FMT_qu, (long long unsigned int)ecid);
+ return ecid_string;
+}
- // Add build information to TSS request
- plist_t tss_request = plist_new_dict();
- plist_dict_insert_item(tss_request, "@APTicket", plist_new_bool(1));
- plist_dict_insert_item(tss_request, "@BBTicket", plist_new_bool(1));
- plist_dict_insert_item(tss_request, "@HostIpAddress", plist_new_string("192.168.0.1"));
- plist_dict_insert_item(tss_request, "@HostPlatformInfo",
+plist_t tss_request_new(plist_t overrides) {
+
+ plist_t request = plist_new_dict();
+
+ plist_dict_insert_item(request, "@Locality", plist_new_string("en_US"));
+ plist_dict_insert_item(request, "@HostPlatformInfo",
#ifdef WIN32
plist_new_string("windows")
#else
plist_new_string("mac")
#endif
);
- plist_dict_insert_item(tss_request, "@Locality", plist_new_string("en_US"));
+
+ plist_dict_insert_item(request, "@VersionInfo", plist_new_string(TSS_CLIENT_VERSION_STRING));
char* guid = generate_guid();
if (guid) {
- plist_dict_insert_item(tss_request, "@UUID", plist_new_string(guid));
+ plist_dict_insert_item(request, "@UUID", plist_new_string(guid));
free(guid);
}
- plist_dict_insert_item(tss_request, "@VersionInfo", plist_new_string("libauthinstall-107.3"));
- plist_dict_insert_item(tss_request, "ApBoardID", plist_new_uint(board_id));
- plist_dict_insert_item(tss_request, "ApChipID", plist_new_uint(chip_id));
- plist_dict_insert_item(tss_request, "ApECID", plist_new_string(ecid_string));
- if (nonce && (nonce_size > 0)) {
- plist_dict_insert_item(tss_request, "ApNonce", plist_new_data((char*)nonce, nonce_size));
+
+ /* apply overrides */
+ if (overrides) {
+ plist_dict_merge(&request, overrides);
+ }
+
+ return request;
+}
+
+int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) {
+ plist_t node = NULL;
+
+ if (!parameters) {
+ error("ERROR: Missing required AP parameters\n");
+ return -1;
+ }
+
+ /* ApNonce */
+ node = plist_dict_get_item(parameters, "ApNonce");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find required ApNonce in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "ApNonce", plist_copy(node));
+ node = NULL;
+
+ plist_dict_insert_item(request, "@ApImg4Ticket", plist_new_bool(1));
+
+ /* ApSecurityMode */
+ node = plist_dict_get_item(request, "ApSecurityMode");
+ if (!node) {
+ /* copy from parameters if available */
+ node = plist_dict_get_item(parameters, "ApSecurityMode");
+ if (!node || plist_get_node_type(node) != PLIST_UINT) {
+ error("ERROR: Unable to find required ApSecurityMode in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "ApSecurityMode", plist_copy(node));
+ node = NULL;
+ }
+
+ /* ApSepNonce */
+ node = plist_dict_get_item(parameters, "ApSepNonce");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find required ApSepNonce in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "ApSepNonce", plist_copy(node));
+ node = NULL;
+
+ return 0;
+}
+
+int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) {
+ plist_t node = NULL;
+
+ if (!parameters) {
+ error("ERROR: Missing required AP parameters\n");
+ return -1;
+ }
+
+ /* ApNonce */
+ node = plist_dict_get_item(parameters, "ApNonce");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find required ApNonce in parameters\n");
+ return -1;
}
- plist_dict_insert_item(tss_request, "ApProductionMode", plist_new_bool(1));
- plist_dict_insert_item(tss_request, "ApSecurityDomain", plist_new_uint(security_domain));
- plist_dict_insert_item(tss_request, "UniqueBuildID", plist_new_data(unique_build_data, unique_build_size));
+ plist_dict_insert_item(request, "ApNonce", plist_copy(node));
+ node = NULL;
+
+ /* @APTicket */
+ plist_dict_insert_item(request, "@APTicket", plist_new_bool(1));
+
+ /* ApECID */
+ node = plist_dict_get_item(parameters, "ApECID");
+ if (!node || plist_get_node_type(node) != PLIST_STRING) {
+ error("ERROR: Unable to find required ApECID in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "ApECID", plist_copy(node));
+ node = NULL;
+
+ /* ApBoardId */
+ node = plist_dict_get_item(request, "ApBoardId");
+ if (!node || plist_get_node_type(node) != PLIST_UINT) {
+ error("ERROR: Unable to find required ApBoardId in request\n");
+ return -1;
+ }
+ node = NULL;
+
+ /* ApChipId */
+ node = plist_dict_get_item(request, "ApChipId");
+ if (!node || plist_get_node_type(node) != PLIST_UINT) {
+ error("ERROR: Unable to find required ApChipId in request\n");
+ return -1;
+ }
+ node = NULL;
+
+ /* ApSecurityDomain */
+ node = plist_dict_get_item(request, "ApSecurityDomain");
+ if (!node || plist_get_node_type(node) != PLIST_STRING) {
+ error("ERROR: Unable to find required ApSecurityDomain in request\n");
+ return -1;
+ }
+ node = NULL;
+
+ /* ApProductionMode */
+ node = plist_dict_get_item(parameters, "ApProductionMode");
+ if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) {
+ error("ERROR: Unable to find required ApProductionMode in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "ApProductionMode", plist_copy(node));
+ node = NULL;
+
+ return 0;
+}
+
+int tss_request_add_baseband_tags(plist_t request, plist_t parameters) {
+ plist_t node = NULL;
+
+ if (!parameters) {
+ error("ERROR: Missing required AP parameters\n");
+ return -1;
+ }
+
+ /* BbNonce */
+ node = plist_dict_get_item(parameters, "BbNonce");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find required BbNonce in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "BbNonce", plist_copy(node));
+ node = NULL;
+
+ /* @BBTicket */
+ plist_dict_insert_item(request, "@BBTicket", plist_new_bool(1));
+
+ /* BbGoldCertId */
+ node = plist_dict_get_item(parameters, "BbGoldCertId");
+ if (!node || plist_get_node_type(node) != PLIST_UINT) {
+ error("ERROR: Unable to find required BbGoldCertId in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "BbGoldCertId", plist_copy(node));
+ node = NULL;
+
+ /* BbSNUM */
+ node = plist_dict_get_item(parameters, "BbSNUM");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find required BbSNUM in parameters\n");
+ return -1;
+ }
+ plist_dict_insert_item(request, "BbSNUM", plist_copy(node));
+ node = NULL;
+
+ return 0;
+}
+
+int tss_request_add_ap_tags_from_manifest(plist_t request, plist_t build_identity, plist_t overrides) {
+ plist_t node = NULL;
+ char* string = NULL;
+
+ /* UniqueBuildID */
+ char* unique_build_data = NULL;
+ uint64_t unique_build_size = 0;
+ node = plist_dict_get_item(build_identity, "UniqueBuildID");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find UniqueBuildID node\n");
+ return -1;
+ }
+ plist_get_data_val(node, &unique_build_data, &unique_build_size);
+ plist_dict_insert_item(request, "UniqueBuildID", plist_new_data(unique_build_data, unique_build_size));
free(unique_build_data);
+ node = NULL;
+
+ /* ApChipID */
+ int chip_id = 0;
+ node = plist_dict_get_item(build_identity, "ApChipID");
+ if (!node || plist_get_node_type(node) != PLIST_STRING) {
+ error("ERROR: Unable to find ApChipID node\n");
+ return -1;
+ }
+ plist_get_string_val(node, &string);
+ sscanf(string, "%x", &chip_id);
+ plist_dict_insert_item(request, "ApChipID", plist_new_uint(chip_id));
+ free(string);
+ string = NULL;
+ node = NULL;
+
+ /* ApBoardID */
+ int board_id = 0;
+ node = plist_dict_get_item(build_identity, "ApBoardID");
+ if (!node || plist_get_node_type(node) != PLIST_STRING) {
+ error("ERROR: Unable to find ApBoardID node\n");
+ return -1;
+ }
+ plist_get_string_val(node, &string);
+ sscanf(string, "%x", &board_id);
+ plist_dict_insert_item(request, "ApBoardID", plist_new_uint(board_id));
+ free(string);
+ string = NULL;
+ node = NULL;
+
+ /* ApSecurityDomain */
+ int security_domain = 0;
+ node = plist_dict_get_item(build_identity, "ApSecurityDomain");
+ if (!node || plist_get_node_type(node) != PLIST_STRING) {
+ error("ERROR: Unable to find ApSecurityDomain node\n");
+ return -1;
+ }
+ plist_get_string_val(node, &string);
+ sscanf(string, "%x", &security_domain);
+ plist_dict_insert_item(request, "ApSecurityDomain", plist_new_string(string));
+ free(string);
+ string = NULL;
+ node = NULL;
- // Add all firmware files to TSS request
+ /* loop over components from build manifest */
plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
error("ERROR: Unable to find restore manifest\n");
- plist_free(tss_request);
- return NULL;
+ return -1;
}
+ /* add components to request */
char* key = NULL;
plist_t manifest_entry = NULL;
plist_dict_iter iter = NULL;
@@ -136,132 +307,73 @@ plist_t tss_create_request(plist_t build_identity, uint64_t ecid, unsigned char*
break;
if (!manifest_entry || plist_get_node_type(manifest_entry) != PLIST_DICT) {
error("ERROR: Unable to fetch BuildManifest entry\n");
- plist_free(tss_request);
- return NULL;
+ return -1;
}
- if ((strcmp(key, "BasebandFirmware") == 0) || (strcmp(key, "OS") == 0)) {
+ /* do not populate BaseBandFirmware, only in basebaseband request */
+ if ((strcmp(key, "BasebandFirmware") == 0)) {
free(key);
continue;
}
- plist_t tss_entry = plist_copy(manifest_entry);
- plist_dict_insert_item(tss_request, key, tss_entry);
- free(key);
- }
+ /* FIXME: populated if ApSupportsImg4 */
+ if ((strcmp(key, "OS") == 0) || (strcmp(key, "Diags") == 0)) {
+ free(key);
+ continue;
+ }
- if (idevicerestore_debug) {
- debug_plist(tss_request);
- }
+ /* copy this entry to request */
+ plist_t tss_entry = plist_copy(manifest_entry);
- return tss_request;
-}
+ /* remove obsolete Info node */
+ plist_dict_remove_item(tss_entry, "Info");
-plist_t tss_create_baseband_request(plist_t build_identity, uint64_t ecid, uint64_t bb_cert_id, unsigned char* bb_snum, uint64_t bb_snum_size, unsigned char* bb_nonce, int bb_nonce_size) {
- uint64_t unique_build_size = 0;
- char* unique_build_data = NULL;
+ /* FIXME: If ApSupportsImg4 */
+ plist_dict_insert_item(tss_entry, "EPRO", plist_new_bool(1));
+ plist_dict_insert_item(tss_entry, "ESEC", plist_new_bool(1));
- plist_t unique_build_node = plist_dict_get_item(build_identity, "UniqueBuildID");
- if (!unique_build_node || plist_get_node_type(unique_build_node) != PLIST_DATA) {
- error("ERROR: Unable to find UniqueBuildID node\n");
- return NULL;
- }
- plist_get_data_val(unique_build_node, &unique_build_data, &unique_build_size);
+ plist_dict_insert_item(request, key, tss_entry);
- int chip_id = 0;
- char* chip_id_string = NULL;
- plist_t chip_id_node = plist_dict_get_item(build_identity, "ApChipID");
- if (!chip_id_node || plist_get_node_type(chip_id_node) != PLIST_STRING) {
- error("ERROR: Unable to find ApChipID node\n");
- return NULL;
+ free(key);
}
- plist_get_string_val(chip_id_node, &chip_id_string);
- sscanf(chip_id_string, "%x", &chip_id);
- int board_id = 0;
- char* board_id_string = NULL;
- plist_t board_id_node = plist_dict_get_item(build_identity, "ApBoardID");
- if (!board_id_node || plist_get_node_type(board_id_node) != PLIST_STRING) {
- error("ERROR: Unable to find ApBoardID node\n");
- return NULL;
+ /* apply overrides */
+ if (overrides) {
+ plist_dict_merge(&request, overrides);
}
- plist_get_string_val(board_id_node, &board_id_string);
- sscanf(board_id_string, "%x", &board_id);
- int security_domain = 0;
- char* security_domain_string = NULL;
- plist_t security_domain_node = plist_dict_get_item(build_identity, "ApSecurityDomain");
- if (!security_domain_node || plist_get_node_type(security_domain_node) != PLIST_STRING) {
- error("ERROR: Unable to find ApSecurityDomain node\n");
- return NULL;
- }
- plist_get_string_val(security_domain_node, &security_domain_string);
- sscanf(security_domain_string, "%x", &security_domain);
+ return 0;
+}
- char ecid_string[ECID_STRSIZE];
- memset(ecid_string, '\0', ECID_STRSIZE);
- if (ecid == 0) {
- error("ERROR: Unable to get ECID\n");
- return NULL;
- }
- snprintf(ecid_string, ECID_STRSIZE, FMT_qu, (long long unsigned int)ecid);
+int tss_request_add_baseband_tags_from_manifest(plist_t request, plist_t build_identity, plist_t overrides) {
+ plist_t bb_node = NULL;
+ /* BbChipID */
int bb_chip_id = 0;
char* bb_chip_id_string = NULL;
- plist_t bb_chip_id_node = plist_dict_get_item(build_identity, "BbChipID");
- if (!bb_chip_id_node || plist_get_node_type(bb_chip_id_node) != PLIST_STRING) {
+ bb_node = plist_dict_get_item(build_identity, "BbChipID");
+ if (!bb_node || plist_get_node_type(bb_node) != PLIST_STRING) {
error("ERROR: Unable to find BbChipID node\n");
- return NULL;
+ return -1;
}
- plist_get_string_val(bb_chip_id_node, &bb_chip_id_string);
+ plist_get_string_val(bb_node, &bb_chip_id_string);
sscanf(bb_chip_id_string, "%x", &bb_chip_id);
+ plist_dict_insert_item(request, "BbChipID", plist_new_uint(bb_chip_id));
+ bb_node = NULL;
- plist_t bbfw_node = plist_access_path(build_identity, 2, "Manifest", "BasebandFirmware");
- if (!bbfw_node || plist_get_node_type(bbfw_node) != PLIST_DICT) {
- error("ERROR: Unable to get BasebandFirmware node\n");
- return NULL;
- }
-
- // Add build information to TSS request
- plist_t tss_request = plist_new_dict();
- plist_dict_insert_item(tss_request, "@BBTicket", plist_new_bool(1));
- plist_dict_insert_item(tss_request, "@HostIpAddress", plist_new_string("192.168.0.1"));
- plist_dict_insert_item(tss_request, "@HostPlatformInfo",
-#ifdef WIN32
- plist_new_string("windows")
-#else
- plist_new_string("mac")
-#endif
- );
- plist_dict_insert_item(tss_request, "@Locality", plist_new_string("en_US"));
-
- char* guid = generate_guid();
- if (guid) {
- plist_dict_insert_item(tss_request, "@UUID", plist_new_string(guid));
- free(guid);
- }
- plist_dict_insert_item(tss_request, "@VersionInfo", plist_new_string("libauthinstall-107.3"));
- plist_dict_insert_item(tss_request, "ApBoardID", plist_new_uint(board_id));
- plist_dict_insert_item(tss_request, "ApChipID", plist_new_uint(chip_id));
- plist_dict_insert_item(tss_request, "ApECID", plist_new_string(ecid_string));
- plist_dict_insert_item(tss_request, "ApProductionMode", plist_new_bool(1));
- plist_dict_insert_item(tss_request, "ApSecurityDomain", plist_new_uint(security_domain));
- plist_dict_insert_item(tss_request, "BasebandFirmware", plist_copy(bbfw_node));
-
- /* Used by XMM 6180/GSM */
- plist_t bb_node = NULL;
- bb_node = plist_dict_get_item(build_identity, "BbSkeyId");
+ /* BbProvisioningManifestKeyHash */
+ bb_node = plist_dict_get_item(build_identity, "BbProvisioningManifestKeyHash");
if (bb_node && plist_get_node_type(bb_node) == PLIST_DATA) {
- plist_dict_insert_item(tss_request, "BbSkeyId", plist_copy(bb_node));
+ plist_dict_insert_item(request, "BbProvisioningManifestKeyHash", plist_copy(bb_node));
} else {
- error("WARNING: Unable to find BbSkeyId node\n");
+ error("WARNING: Unable to find BbProvisioningManifestKeyHash node\n");
}
bb_node = NULL;
- /* Used by Qualcomm MDM6610 */
+ /* BbActivationManifestKeyHash - Used by Qualcomm MDM6610 */
bb_node = plist_dict_get_item(build_identity, "BbActivationManifestKeyHash");
if (bb_node && plist_get_node_type(bb_node) == PLIST_DATA) {
- plist_dict_insert_item(tss_request, "BbActivationManifestKeyHash", plist_copy(bb_node));
+ plist_dict_insert_item(request, "BbActivationManifestKeyHash", plist_copy(bb_node));
} else {
error("WARNING: Unable to find BbActivationManifestKeyHash node\n");
}
@@ -269,39 +381,45 @@ plist_t tss_create_baseband_request(plist_t build_identity, uint64_t ecid, uint6
bb_node = plist_dict_get_item(build_identity, "BbCalibrationManifestKeyHash");
if (bb_node && plist_get_node_type(bb_node) == PLIST_DATA) {
- plist_dict_insert_item(tss_request, "BbCalibrationManifestKeyHash", plist_copy(bb_node));
+ plist_dict_insert_item(request, "BbCalibrationManifestKeyHash", plist_copy(bb_node));
} else {
error("WARNING: Unable to find BbCalibrationManifestKeyHash node\n");
}
bb_node = NULL;
- plist_dict_insert_item(tss_request, "BbChipID", plist_new_uint(bb_chip_id));
- plist_dict_insert_item(tss_request, "BbGoldCertId", plist_new_uint(bb_cert_id));
-
- if (bb_nonce && (bb_nonce_size > 0)) {
- plist_dict_insert_item(tss_request, "BbNonce", plist_new_data((char*)bb_nonce, bb_nonce_size));
+ /* BbFactoryActivationManifestKeyHash */
+ bb_node = plist_dict_get_item(build_identity, "BbFactoryActivationManifestKeyHash");
+ if (bb_node && plist_get_node_type(bb_node) == PLIST_DATA) {
+ plist_dict_insert_item(request, "BbFactoryActivationManifestKeyHash", plist_copy(bb_node));
+ } else {
+ error("WARNING: Unable to find BbFactoryActivationManifestKeyHash node\n");
}
+ bb_node = NULL;
- bb_node = plist_dict_get_item(build_identity, "BbProvisioningManifestKeyHash");
+ /* BbSkeyId - Used by XMM 6180/GSM */
+ bb_node = plist_dict_get_item(build_identity, "BbSkeyId");
if (bb_node && plist_get_node_type(bb_node) == PLIST_DATA) {
- plist_dict_insert_item(tss_request, "BbProvisioningManifestKeyHash", plist_copy(bb_node));
+ plist_dict_insert_item(request, "BbSkeyId", plist_copy(bb_node));
} else {
- error("WARNING: Unable to find BbProvisioningManifestKeyHash node\n");
+ error("WARNING: Unable to find BbSkeyId node\n");
}
bb_node = NULL;
- if (bb_snum && bb_snum_size > 0) {
- plist_dict_insert_item(tss_request, "BbSNUM", plist_new_data((char*)bb_snum, bb_snum_size));
+ /* BasebandFirmware */
+ bb_node = plist_access_path(build_identity, 2, "Manifest", "BasebandFirmware");
+ if (!bb_node || plist_get_node_type(bb_node) != PLIST_DICT) {
+ error("ERROR: Unable to get BasebandFirmware node\n");
+ return -1;
}
+ plist_dict_insert_item(request, "BasebandFirmware", plist_copy(bb_node));
+ bb_node = NULL;
- plist_dict_insert_item(tss_request, "UniqueBuildID", plist_new_data(unique_build_data, unique_build_size));
- free(unique_build_data);
-
- if (idevicerestore_debug) {
- debug_plist(tss_request);
+ /* apply overrides */
+ if (overrides) {
+ plist_dict_merge(&request, overrides);
}
- return tss_request;
+ return 0;
}
size_t tss_write_callback(char* data, size_t size, size_t nmemb, tss_response* response) {
@@ -316,7 +434,7 @@ size_t tss_write_callback(char* data, size_t size, size_t nmemb, tss_response* r
return total;
}
-plist_t tss_send_request(plist_t tss_request, const char* server_url_string) {
+plist_t tss_request_send(plist_t tss_request, const char* server_url_string) {
curl_global_init(CURL_GLOBAL_ALL);
char* request = NULL;
@@ -462,33 +580,47 @@ plist_t tss_send_request(plist_t tss_request, const char* server_url_string) {
return tss_response;
}
-int tss_get_ticket(plist_t tss, unsigned char** ticket, unsigned int* tlen) {
- plist_t entry_node = plist_dict_get_item(tss, "APTicket");
- if (!entry_node || plist_get_node_type(entry_node) != PLIST_DATA) {
- error("ERROR: Unable to find APTicket entry in TSS response\n");
+static tss_response_get_data_by_key(plist_t response, const char* name, unsigned char** buffer, unsigned int* length) {
+
+ plist_t node = plist_dict_get_item(response, name);
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find %s entry in TSS response\n", name);
return -1;
}
+
char *data = NULL;
uint64_t len = 0;
- plist_get_data_val(entry_node, &data, &len);
+ plist_get_data_val(node, &data, &len);
if (data) {
- *tlen = (unsigned int)len;
- *ticket = (unsigned char*)data;
+ *length = (unsigned int)len;
+ *buffer = (unsigned char*)data;
return 0;
} else {
- error("ERROR: Unable to get APTicket data from TSS response\n");
+ error("ERROR: Unable to get %s data from TSS response\n", name);
return -1;
}
}
-int tss_get_entry_path(plist_t tss, const char* entry, char** path) {
+int tss_response_get_ap_img4_ticket(plist_t response, unsigned char** ticket, unsigned int* length) {
+ return tss_response_get_data_by_key(response, "APImg4Ticket", ticket, length);
+}
+
+int tss_response_get_ap_ticket(plist_t response, unsigned char** ticket, unsigned int* length) {
+ return tss_response_get_data_by_key(response, "APTicket", ticket, length);
+}
+
+int tss_response_get_baseband_ticket(plist_t response, unsigned char** ticket, unsigned int* length) {
+ return tss_response_get_data_by_key(response, "BBTicket", ticket, length);
+}
+
+int tss_response_get_path_by_entry(plist_t response, const char* entry, char** path) {
char* path_string = NULL;
plist_t path_node = NULL;
plist_t entry_node = NULL;
*path = NULL;
- entry_node = plist_dict_get_item(tss, entry);
+ entry_node = plist_dict_get_item(response, entry);
if (!entry_node || plist_get_node_type(entry_node) != PLIST_DICT) {
error("ERROR: Unable to find %s entry in TSS response\n", entry);
return -1;
@@ -505,7 +637,7 @@ int tss_get_entry_path(plist_t tss, const char* entry, char** path) {
return 0;
}
-int tss_get_blob_by_path(plist_t tss, const char* path, unsigned char** blob) {
+int tss_response_get_blob_by_path(plist_t tss, const char* path, unsigned char** blob) {
int i = 0;
uint32_t tss_size = 0;
uint64_t blob_size = 0;
@@ -558,7 +690,7 @@ int tss_get_blob_by_path(plist_t tss, const char* path, unsigned char** blob) {
return 0;
}
-int tss_get_blob_by_name(plist_t tss, const char* entry, unsigned char** blob) {
+int tss_response_get_blob_by_entry(plist_t response, const char* entry, unsigned char** blob) {
uint64_t blob_size = 0;
char* blob_data = NULL;
plist_t blob_node = NULL;
@@ -566,7 +698,7 @@ int tss_get_blob_by_name(plist_t tss, const char* entry, unsigned char** blob) {
*blob = NULL;
- tss_entry = plist_dict_get_item(tss, entry);
+ tss_entry = plist_dict_get_item(response, entry);
if (!tss_entry || plist_get_node_type(tss_entry) != PLIST_DICT) {
error("ERROR: Unable to find %s entry in TSS response\n", entry);
return -1;
diff --git a/src/tss.h b/src/tss.h
index b5b322a..f468707 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -2,6 +2,7 @@
* tss.h
* Definitions for communicating with Apple's TSS server.
*
+ * Copyright (c) 2013 Martin Szulecki. All Rights Reserved.
* Copyright (c) 2012 Nikias Bassen. All Rights Reserved.
* Copyright (c) 2010 Joshua Hill. All Rights Reserved.
*
@@ -29,14 +30,29 @@ extern "C" {
#include <plist/plist.h>
-plist_t tss_send_request(plist_t request, const char* server_url_string);
-plist_t tss_create_request(plist_t build_identity, uint64_t ecid, unsigned char* nonce, int nonce_size);
-plist_t tss_create_baseband_request(plist_t build_identity, uint64_t ecid, uint64_t bb_cert_id, unsigned char* bb_snum, uint64_t bb_snum_size, unsigned char* bb_nonce, int bb_nonce_size);
-int tss_get_ticket(plist_t tss, unsigned char** ticket, unsigned int* tlen);
-int tss_get_entry_path(plist_t tss, const char* entry, char** path);
-int tss_get_blob_by_path(plist_t tss, const char* path, unsigned char** blob);
-int tss_get_blob_by_name(plist_t tss, const char* entry, unsigned char** blob);
+/* request */
+plist_t tss_request_new(plist_t overrides);
+int tss_request_add_ap_tags_from_manifest(plist_t request, plist_t build_identity, plist_t overrides);
+int tss_request_add_baseband_tags_from_manifest(plist_t request, plist_t build_identity, plist_t overrides);
+
+int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters);
+int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters);
+int tss_request_add_baseband_tags(plist_t request, plist_t parameters);
+
+/* i/o */
+plist_t tss_request_send(plist_t request, const char* server_url_string);
+
+/* response */
+int tss_response_get_ap_img4_ticket(plist_t response, unsigned char** ticket, unsigned int* length);
+int tss_response_get_ap_ticket(plist_t response, unsigned char** ticket, unsigned int* length);
+int tss_response_get_baseband_ticket(plist_t response, unsigned char** ticket, unsigned int* length);
+int tss_response_get_path_by_entry(plist_t response, const char* entry, char** path);
+int tss_response_get_blob_by_path(plist_t response, const char* path, unsigned char** blob);
+int tss_response_get_blob_by_entry(plist_t response, const char* entry, unsigned char** blob);
+
+/* helpers */
+char* ecid_to_string(uint64_t ecid);
#ifdef __cplusplus
}