diff options
author | Martin Szulecki | 2013-11-19 22:04:30 +0100 |
---|---|---|
committer | Nikias Bassen | 2013-11-19 22:04:30 +0100 |
commit | 669ac822c564c5a6358daa7a49f6d0b336591558 (patch) | |
tree | d43ba8b1d4bb3c7008b483fc8f1896f41797fdb1 /src | |
parent | 26f34f031287b232b45df00e566c356fb95c399a (diff) | |
download | idevicerestore-669ac822c564c5a6358daa7a49f6d0b336591558.tar.gz idevicerestore-669ac822c564c5a6358daa7a49f6d0b336591558.tar.bz2 |
tss: Refactor TSS handlers for Image4 support and flexibility
Diffstat (limited to 'src')
-rw-r--r-- | src/dfu.c | 6 | ||||
-rw-r--r-- | src/idevicerestore.c | 43 | ||||
-rw-r--r-- | src/idevicerestore.h | 2 | ||||
-rw-r--r-- | src/recovery.c | 4 | ||||
-rw-r--r-- | src/restore.c | 23 | ||||
-rw-r--r-- | src/tss.c | 510 | ||||
-rw-r--r-- | src/tss.h | 30 |
7 files changed, 403 insertions, 215 deletions
@@ -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"); @@ -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; @@ -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 } |