diff options
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  } | 
