diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/asr.c | 34 | ||||
-rw-r--r-- | src/asr.h | 4 | ||||
-rw-r--r-- | src/common.c | 174 | ||||
-rw-r--r-- | src/common.h | 9 | ||||
-rw-r--r-- | src/dfu.c | 3 | ||||
-rw-r--r-- | src/fixedint.h | 72 | ||||
-rw-r--r-- | src/idevicerestore.c | 62 | ||||
-rw-r--r-- | src/img4.c | 23 | ||||
-rw-r--r-- | src/ipsw.c | 187 | ||||
-rw-r--r-- | src/ipsw.h | 3 | ||||
-rw-r--r-- | src/normal.c | 10 | ||||
-rw-r--r-- | src/recovery.c | 3 | ||||
-rw-r--r-- | src/restore.c | 1100 | ||||
-rw-r--r-- | src/restore.h | 17 | ||||
-rw-r--r-- | src/sha1.c | 294 | ||||
-rw-r--r-- | src/sha1.h | 44 | ||||
-rw-r--r-- | src/sha512.c | 314 | ||||
-rw-r--r-- | src/sha512.h | 32 | ||||
-rw-r--r-- | src/tss.c | 1796 | ||||
-rw-r--r-- | src/tss.h | 76 |
21 files changed, 1144 insertions, 3121 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 722487a..80f02f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,9 +6,9 @@ AM_CFLAGS = \ $(libusbmuxd_CFLAGS) \ $(libplist_CFLAGS) \ $(limd_glue_CFLAGS) \ + $(libtatsu_CFLAGS) \ $(libzip_CFLAGS) \ $(zlib_CFLAGS) \ - $(openssl_CFLAGS) \ $(libcurl_CFLAGS) AM_LDFLAGS = \ @@ -18,9 +18,9 @@ AM_LDFLAGS = \ $(libusbmuxd_LIBS) \ $(libplist_LIBS) \ $(limd_glue_LIBS) \ + $(libtatsu_LIBS) \ $(libzip_LIBS) \ $(zlib_LIBS) \ - $(openssl_LIBS) \ $(libcurl_LIBS) AM_LDADD = $(AC_LDADD) @@ -31,7 +31,6 @@ idevicerestore_SOURCES = \ idevicerestore.c idevicerestore.h \ endianness.h \ common.c common.h \ - tss.c tss.h \ fls.c fls.h \ mbn.c mbn.h \ img3.c img3.h \ @@ -49,9 +48,6 @@ idevicerestore_SOURCES = \ limera1n.c limera1n.h \ download.c download.h \ locking.c locking.h -if USE_INTERNAL_SHA -idevicerestore_SOURCES += sha1.c sha1.h sha512.c sha512.h fixedint.h -endif idevicerestore_CFLAGS = $(AM_CFLAGS) idevicerestore_LDFLAGS = $(AM_LDFLAGS) idevicerestore_LDADD = $(AM_LDADD) @@ -30,15 +30,8 @@ #include <unistd.h> #include <errno.h> #include <libimobiledevice/libimobiledevice.h> -#ifdef HAVE_OPENSSL -#include <openssl/sha.h> -#else -#include "sha1.h" -#define SHA_CTX SHA1_CTX -#define SHA1_Init SHA1Init -#define SHA1_Update SHA1Update -#define SHA1_Final SHA1Final -#endif + +#include <libimobiledevice-glue/sha.h> #include "asr.h" #include "idevicerestore.h" @@ -47,7 +40,6 @@ #define ASR_VERSION 1 #define ASR_STREAM_ID 1 -#define ASR_PORT 12345 #define ASR_BUFFER_SIZE 65536 #define ASR_FEC_SLICE_STRIDE 40 #define ASR_PACKETS_PER_FEC 25 @@ -55,7 +47,7 @@ #define ASR_PAYLOAD_CHUNK_SIZE 131072 #define ASR_CHECKSUM_CHUNK_SIZE 131072 -int asr_open_with_timeout(idevice_t device, asr_client_t* asr) +int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port) { int i = 0; int attempts = 10; @@ -68,9 +60,13 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr) return -1; } - debug("Connecting to ASR\n"); + if (port == 0) { + port = ASR_DEFAULT_PORT; + } + debug("Connecting to ASR on port %u\n", port); + for (i = 1; i <= attempts; i++) { - device_error = idevice_connect(device, ASR_PORT, &connection); + device_error = idevice_connect(device, port, &connection); if (device_error == IDEVICE_E_SUCCESS) { break; } @@ -343,12 +339,6 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file) data = (char*)malloc(ASR_PAYLOAD_CHUNK_SIZE + 20); - SHA_CTX sha1; - - if (asr->checksum_chunks) { - SHA1_Init(&sha1); - } - i = length; int retry = 3; while(i > 0 && retry >= 0) { @@ -367,11 +357,11 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file) sendsize = size; if (asr->checksum_chunks) { - SHA1((unsigned char*)data, size, (unsigned char*)(data+size)); + sha1((unsigned char*)data, size, (unsigned char*)(data+size)); sendsize += 20; } if (asr_send_buffer(asr, data, sendsize) < 0) { - error("ERROR: Unable to send filesystem payload\n"); + error("Unable to send filesystem payload chunk, retrying...\n"); retry--; continue; } @@ -387,5 +377,5 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file) } free(data); - return 0; + return (i == 0) ? 0 : -1; } @@ -30,6 +30,8 @@ extern "C" { #include <libimobiledevice/libimobiledevice.h> +#define ASR_DEFAULT_PORT 12345 + typedef void (*asr_progress_cb_t)(double, void*); struct asr_client { @@ -44,7 +46,7 @@ typedef struct asr_client *asr_client_t; struct ipsw_file_handle; typedef struct ipsw_file_handle* ipsw_file_handle_t; -int asr_open_with_timeout(idevice_t device, asr_client_t* asr); +int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port); void asr_set_progress_callback(asr_client_t asr, asr_progress_cb_t, void* userdata); int asr_send(asr_client_t asr, plist_t data); int asr_receive(asr_client_t asr, plist_t* data); diff --git a/src/common.c b/src/common.c index 499509d..d31c558 100644 --- a/src/common.c +++ b/src/common.c @@ -35,6 +35,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <ctype.h> +#include <libimobiledevice-glue/thread.h> #ifdef WIN32 #include <windows.h> @@ -79,17 +80,30 @@ static int info_disabled = 0; static int error_disabled = 0; static int debug_disabled = 0; +static mutex_t log_mutex; +static thread_once_t init_once = THREAD_ONCE_INIT; + +static void _log_init(void) +{ + mutex_init(&log_mutex); +} + void info(const char* format, ...) { if (info_disabled) return; + thread_once(&init_once, _log_init); + mutex_lock(&log_mutex); va_list vargs; va_start(vargs, format); vfprintf((info_stream) ? info_stream : stdout, format, vargs); va_end(vargs); + mutex_unlock(&log_mutex); } void error(const char* format, ...) { + thread_once(&init_once, _log_init); + mutex_lock(&log_mutex); va_list vargs, vargs2; va_start(vargs, format); va_copy(vargs2, vargs); @@ -99,6 +113,7 @@ void error(const char* format, ...) vfprintf((error_stream) ? error_stream : stderr, format, vargs2); } va_end(vargs2); + mutex_unlock(&log_mutex); } void debug(const char* format, ...) @@ -107,10 +122,13 @@ void debug(const char* format, ...) if (!idevicerestore_debug) { return; } + thread_once(&init_once, _log_init); + mutex_lock(&log_mutex); va_list vargs; va_start(vargs, format); vfprintf((debug_stream) ? debug_stream : stderr, format, vargs); va_end(vargs); + mutex_unlock(&log_mutex); } void idevicerestore_set_info_stream(FILE* strm) @@ -227,9 +245,9 @@ void debug_plist(plist_t plist) { char* data = NULL; plist_to_xml(plist, &data, &size); if (size <= MAX_PRINT_LEN) - info("%s:printing %i bytes plist:\n%s", __FILE__, size, data); + info("printing %i bytes plist:\n%s", size, data); else - info("%s:supressed printing %i bytes plist...\n", __FILE__, size); + info("supressed printing %i bytes plist...\n", size); free(data); } @@ -239,13 +257,13 @@ void print_progress_bar(double progress) { int i = 0; if(progress < 0) return; if(progress > 100) progress = 100; - info("\r["); + fprintf((info_stream) ? info_stream : stdout, "\r["); for(i = 0; i < 50; i++) { - if(i < progress / 2) info("="); - else info(" "); + if(i < progress / 2) fprintf((info_stream) ? info_stream : stdout, "="); + else fprintf((info_stream) ? info_stream : stdout, " "); } - info("] %5.1f%%", progress); - if(progress >= 100) info("\n"); + fprintf((info_stream) ? info_stream : stdout, "] %5.1f%%", progress); + if(progress >= 100) fprintf((info_stream) ? info_stream : stdout, "\n"); fflush((info_stream) ? info_stream : stdout); #endif } @@ -464,6 +482,8 @@ char *get_temp_filename(const char *prefix) void idevicerestore_progress(struct idevicerestore_client_t* client, int step, double progress) { + thread_once(&init_once, _log_init); + mutex_lock(&log_mutex); if(client && client->progress_cb) { client->progress_cb(step, progress, client->progress_cb_data); } else { @@ -472,6 +492,7 @@ void idevicerestore_progress(struct idevicerestore_client_t* client, int step, d print_progress_bar(100.0 * progress); } } + mutex_unlock(&log_mutex); } #ifndef HAVE_STRSEP @@ -558,145 +579,6 @@ void get_user_input(char *buf, int maxlen, int secure) buf[len] = 0; } -uint64_t _plist_dict_get_uint(plist_t dict, const char *key) -{ - uint64_t uintval = 0; - char *strval = NULL; - uint64_t strsz = 0; - plist_t node = plist_dict_get_item(dict, key); - if (!node) { - return uintval; - } - switch (plist_get_node_type(node)) { - case PLIST_UINT: - plist_get_uint_val(node, &uintval); - break; - case PLIST_STRING: - plist_get_string_val(node, &strval); - if (strval) { - uintval = strtoull(strval, NULL, 0); - free(strval); - } - break; - case PLIST_DATA: - plist_get_data_val(node, &strval, &strsz); - if (strval) { - if (strsz == 8) { - uintval = le64toh(*(uint64_t*)strval); - } else if (strsz == 4) { - uintval = le32toh(*(uint32_t*)strval); - } else if (strsz == 2) { - uintval = le16toh(*(uint16_t*)strval); - } else if (strsz == 1) { - uintval = strval[0]; - } else { - error("%s: ERROR: invalid size %" PRIu64 " for data to integer conversion\n", __func__, strsz); - } - free(strval); - } - break; - default: - break; - } - return uintval; -} - -uint8_t _plist_dict_get_bool(plist_t dict, const char *key) -{ - uint8_t bval = 0; - uint64_t uintval = 0; - char *strval = NULL; - uint64_t strsz = 0; - plist_t node = plist_dict_get_item(dict, key); - if (!node) { - return 0; - } - switch (plist_get_node_type(node)) { - case PLIST_BOOLEAN: - plist_get_bool_val(node, &bval); - break; - case PLIST_UINT: - plist_get_uint_val(node, &uintval); - bval = (uint8_t)uintval; - break; - case PLIST_STRING: - plist_get_string_val(node, &strval); - if (strval) { - if (strcmp(strval, "true")) { - bval = 1; - } else if (strcmp(strval, "false")) { - bval = 0; - } - free(strval); - } - break; - case PLIST_DATA: - plist_get_data_val(node, &strval, &strsz); - if (strval) { - if (strsz == 1) { - bval = strval[0]; - } else { - error("%s: ERROR: invalid size %" PRIu64 " for data to boolean conversion\n", __func__, strsz); - } - free(strval); - } - break; - default: - break; - } - return bval; -} - -int _plist_dict_copy_uint(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) -{ - if (plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key) == NULL) { - return -1; - } - uint64_t u64val = _plist_dict_get_uint(source_dict, (alt_source_key) ? alt_source_key : key); - plist_dict_set_item(target_dict, key, plist_new_uint(u64val)); - return 0; -} - -int _plist_dict_copy_bool(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) -{ - if (plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key) == NULL) { - return -1; - } - uint64_t bval = _plist_dict_get_bool(source_dict, (alt_source_key) ? alt_source_key : key); - plist_dict_set_item(target_dict, key, plist_new_bool(bval)); - return 0; -} - -int _plist_dict_copy_data(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) -{ - plist_t node = plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key); - if (!PLIST_IS_DATA(node)) { - return -1; - } - plist_dict_set_item(target_dict, key, plist_copy(node)); - return 0; -} - -int _plist_dict_copy_string(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) -{ - plist_t node = plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key); - if (!PLIST_IS_STRING(node)) { - return -1; - } - plist_dict_set_item(target_dict, key, plist_copy(node)); - return 0; -} - -int _plist_dict_copy_item(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) -{ - plist_t node = plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key); - if (!node) { - return -1; - } - plist_dict_set_item(target_dict, key, plist_copy(node)); - return 0; -} - const char* path_get_basename(const char* path) { #ifdef WIN32 diff --git a/src/common.h b/src/common.h index 9b3c1e3..8085a1a 100644 --- a/src/common.h +++ b/src/common.h @@ -134,6 +134,7 @@ struct idevicerestore_client_t { char* restore_variant; char* filesystem; int delete_fs; + int async_err; }; extern struct idevicerestore_mode_t idevicerestore_modes[]; @@ -191,14 +192,6 @@ char* realpath(const char *filename, char *resolved_name); void get_user_input(char *buf, int maxlen, int secure); -uint8_t _plist_dict_get_bool(plist_t dict, const char *key); -uint64_t _plist_dict_get_uint(plist_t dict, const char *key); -int _plist_dict_copy_uint(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); -int _plist_dict_copy_bool(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); -int _plist_dict_copy_data(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); -int _plist_dict_copy_string(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); -int _plist_dict_copy_item(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); - const char* path_get_basename(const char* path); #ifdef __cplusplus @@ -27,8 +27,9 @@ #include <unistd.h> #include <libirecovery.h> +#include <libtatsu/tss.h> + #include "dfu.h" -#include "tss.h" #include "recovery.h" #include "idevicerestore.h" #include "common.h" diff --git a/src/fixedint.h b/src/fixedint.h deleted file mode 100644 index 1a8745b..0000000 --- a/src/fixedint.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Portable header to provide the 32 and 64 bits type. - - Not a compatible replacement for <stdint.h>, do not blindly use it as such. -*/ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED) - #include <stdint.h> - #define FIXEDINT_H_INCLUDED - - #if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C) - #include <limits.h> - #define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) - #endif -#endif - - -#ifndef FIXEDINT_H_INCLUDED - #define FIXEDINT_H_INCLUDED - - #include <limits.h> - - /* (u)int32_t */ - #ifndef uint32_t - #if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long uint32_t; - #elif (UINT_MAX == 0xffffffffUL) - typedef unsigned int uint32_t; - #elif (USHRT_MAX == 0xffffffffUL) - typedef unsigned short uint32_t; - #endif - #endif - - - #ifndef int32_t - #if (LONG_MAX == 0x7fffffffL) - typedef signed long int32_t; - #elif (INT_MAX == 0x7fffffffL) - typedef signed int int32_t; - #elif (SHRT_MAX == 0x7fffffffL) - typedef signed short int32_t; - #endif - #endif - - - /* (u)int64_t */ - #if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L) - typedef long long int64_t; - typedef unsigned long long uint64_t; - - #define UINT64_C(v) v ##ULL - #define INT64_C(v) v ##LL - #elif defined(__GNUC__) - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; - - #define UINT64_C(v) v ##ULL - #define INT64_C(v) v ##LL - #elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC) - typedef long long int64_t; - typedef unsigned long long uint64_t; - - #define UINT64_C(v) v ##ULL - #define INT64_C(v) v ##LL - #elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC) - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - - #define UINT64_C(v) v ##UI64 - #define INT64_C(v) v ##I64 - #endif -#endif diff --git a/src/idevicerestore.c b/src/idevicerestore.c index fdb340e..8de9186 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -38,18 +38,12 @@ #include <curl/curl.h> -#ifdef HAVE_OPENSSL -#include <openssl/sha.h> -#else -#include "sha512.h" -#define SHA384 sha384 -#endif - +#include <libimobiledevice-glue/sha.h> #include <libimobiledevice-glue/utils.h> +#include <libtatsu/tss.h> #include "ace3.h" #include "dfu.h" -#include "tss.h" #include "img3.h" #include "img4.h" #include "ipsw.h" @@ -359,6 +353,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client) idevice_set_debug_level(1); irecv_set_debug_level(1); } + tss_set_debug_level(client->debug_level); } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.0); @@ -724,12 +719,12 @@ int idevicerestore_start(struct idevicerestore_client_t* client) return -1; } - unsigned int b_pdfu_cpid = (unsigned int)_plist_dict_get_uint(build_identity, "USBPortController1,ChipID"); + unsigned int b_pdfu_cpid = (unsigned int)plist_dict_get_uint(build_identity, "USBPortController1,ChipID"); if (b_pdfu_cpid != pdfu_cpid) { error("ERROR: cpid 0x%02x doesn't match USBPortController1,ChipID in build identity (0x%02x)\n", pdfu_cpid, b_pdfu_cpid); return -1; } - unsigned int b_pdfu_bdid = (unsigned int)_plist_dict_get_uint(build_identity, "USBPortController1,BoardID"); + unsigned int b_pdfu_bdid = (unsigned int)plist_dict_get_uint(build_identity, "USBPortController1,BoardID"); if (b_pdfu_bdid != pdfu_bdid) { error("ERROR: bdid 0x%x doesn't match USBPortController1,BoardID in build identity (0x%x)\n", pdfu_bdid, b_pdfu_bdid); return -1; @@ -738,9 +733,9 @@ int idevicerestore_start(struct idevicerestore_client_t* client) plist_t parameters = plist_new_dict(); plist_dict_set_item(parameters, "@USBPortController1,Ticket", plist_new_bool(1)); plist_dict_set_item(parameters, "USBPortController1,ECID", plist_new_int(client->ecid)); - _plist_dict_copy_item(parameters, build_identity, "USBPortController1,BoardID", NULL); - _plist_dict_copy_item(parameters, build_identity, "USBPortController1,ChipID", NULL); - _plist_dict_copy_item(parameters, build_identity, "USBPortController1,SecurityDomain", NULL); + plist_dict_copy_item(parameters, build_identity, "USBPortController1,BoardID", NULL); + plist_dict_copy_item(parameters, build_identity, "USBPortController1,ChipID", NULL); + plist_dict_copy_item(parameters, build_identity, "USBPortController1,SecurityDomain", NULL); plist_dict_set_item(parameters, "USBPortController1,SecurityMode", plist_new_bool(1)); plist_dict_set_item(parameters, "USBPortController1,ProductionMode", plist_new_bool(1)); plist_t usbf = plist_access_path(build_identity, 2, "Manifest", "USBPortController1,USBFirmware"); @@ -1236,7 +1231,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client) } if (client->mode == MODE_RESTORE && client->root_ticket) { - plist_t ap_ticket = plist_new_data(client->root_ticket, client->root_ticket_len); + plist_t ap_ticket = plist_new_data((char*)client->root_ticket, client->root_ticket_len); if (!ap_ticket) { error("ERROR: Failed to create ApImg4Ticket node value.\n"); return -1; @@ -1494,7 +1489,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client) // device is finally in restore mode, let's do this if (client->mode == MODE_RESTORE) { if ((client->flags & FLAG_NO_RESTORE) != 0) { - info("Device is now in restore mode. Exiting as requested."); + info("Device is now in restore mode. Exiting as requested.\n"); return 0; } client->ignore_device_add_events = 1; @@ -1519,10 +1514,11 @@ int idevicerestore_start(struct idevicerestore_client_t* client) } } - info("DONE\n"); - if (result == 0) { + info("DONE\n"); idevicerestore_progress(client, RESTORE_NUM_STEPS-1, 1.0); + } else { + info("RESTORE FAILED\n"); } if (build_identity_needs_free) @@ -2169,7 +2165,7 @@ int get_preboard_manifest(struct idevicerestore_client_t* client, plist_t build_ return -1; } - plist_dict_set_item(parameters, "_OnlyFWOrTrustedComponents", plist_new_bool(1)); + plist_dict_set_item(parameters, "_OnlyFWComponents", plist_new_bool(1)); /* add tags from manifest */ if (tss_request_add_ap_tags(request, parameters, NULL) < 0) { @@ -2331,20 +2327,20 @@ int get_tss_response(struct idevicerestore_client_t* client, plist_t build_ident plist_t pinfo = NULL; normal_get_preflight_info(client, &pinfo); if (pinfo) { - _plist_dict_copy_data(parameters, pinfo, "BbNonce", "Nonce"); - _plist_dict_copy_uint(parameters, pinfo, "BbChipID", "ChipID"); - _plist_dict_copy_uint(parameters, pinfo, "BbGoldCertId", "CertID"); - _plist_dict_copy_data(parameters, pinfo, "BbSNUM", "ChipSerialNo"); + plist_dict_copy_data(parameters, pinfo, "BbNonce", "Nonce"); + plist_dict_copy_uint(parameters, pinfo, "BbChipID", "ChipID"); + plist_dict_copy_uint(parameters, pinfo, "BbGoldCertId", "CertID"); + plist_dict_copy_data(parameters, pinfo, "BbSNUM", "ChipSerialNo"); /* add baseband parameters */ tss_request_add_baseband_tags(request, parameters, NULL); - _plist_dict_copy_uint(parameters, pinfo, "eUICC,ChipID", "EUICCChipID"); - if (_plist_dict_get_uint(parameters, "eUICC,ChipID") >= 5) { - _plist_dict_copy_data(parameters, pinfo, "eUICC,EID", "EUICCCSN"); - _plist_dict_copy_data(parameters, pinfo, "eUICC,RootKeyIdentifier", "EUICCCertIdentifier"); - _plist_dict_copy_data(parameters, pinfo, "EUICCGoldNonce", NULL); - _plist_dict_copy_data(parameters, pinfo, "EUICCMainNonce", NULL); + plist_dict_copy_uint(parameters, pinfo, "eUICC,ChipID", "EUICCChipID"); + if (plist_dict_get_uint(parameters, "eUICC,ChipID") >= 5) { + plist_dict_copy_data(parameters, pinfo, "eUICC,EID", "EUICCCSN"); + plist_dict_copy_data(parameters, pinfo, "eUICC,RootKeyIdentifier", "EUICCCertIdentifier"); + plist_dict_copy_data(parameters, pinfo, "EUICCGoldNonce", NULL); + plist_dict_copy_data(parameters, pinfo, "EUICCMainNonce", NULL); /* add vinyl parameters */ tss_request_add_vinyl_tags(request, parameters, NULL); @@ -2494,14 +2490,14 @@ int get_recovery_os_local_policy_tss_response( // Add Ap,LocalPolicy uint8_t digest[SHA384_DIGEST_LENGTH]; - SHA384(lpol_file, lpol_file_length, digest); + sha384(lpol_file, lpol_file_length, digest); plist_t lpol = plist_new_dict(); plist_dict_set_item(lpol, "Digest", plist_new_data((char*)digest, SHA384_DIGEST_LENGTH)); plist_dict_set_item(lpol, "Trusted", plist_new_bool(1)); plist_dict_set_item(parameters, "Ap,LocalPolicy", lpol); - _plist_dict_copy_data(parameters, args, "Ap,NextStageIM4MHash", NULL); - _plist_dict_copy_data(parameters, args, "Ap,RecoveryOSPolicyNonceHash", NULL); + plist_dict_copy_data(parameters, args, "Ap,NextStageIM4MHash", NULL); + plist_dict_copy_data(parameters, args, "Ap,RecoveryOSPolicyNonceHash", NULL); plist_t vol_uuid_node = plist_dict_get_item(args, "Ap,VolumeUUID"); char* vol_uuid_str = NULL; @@ -2589,7 +2585,7 @@ int get_local_policy_tss_response(struct idevicerestore_client_t* client, plist_ // Add Ap,LocalPolicy uint8_t digest[SHA384_DIGEST_LENGTH]; - SHA384(lpol_file, lpol_file_length, digest); + sha384(lpol_file, lpol_file_length, digest); plist_t lpol = plist_new_dict(); plist_dict_set_item(lpol, "Digest", plist_new_data((char*)digest, SHA384_DIGEST_LENGTH)); plist_dict_set_item(lpol, "Trusted", plist_new_bool(1)); @@ -2602,7 +2598,7 @@ int get_local_policy_tss_response(struct idevicerestore_client_t* client, plist_ tss_response_get_ap_img4_ticket(client->tss, &ticket, &ticket_length); // Hash it and add it as Ap,NextStageIM4MHash uint8_t hash[SHA384_DIGEST_LENGTH]; - SHA384(ticket, ticket_length, hash); + sha384(ticket, ticket_length, hash); plist_dict_set_item(parameters, "Ap,NextStageIM4MHash", plist_new_data((char*)hash, SHA384_DIGEST_LENGTH)); /* create basic request */ @@ -22,9 +22,10 @@ #include <stdlib.h> #include <string.h> +#include <libtatsu/tss.h> + #include "common.h" #include "img4.h" -#include "tss.h" #define ASN1_PRIVATE 0xc0 #define ASN1_PRIMITIVE_TAG 0x1f @@ -705,13 +706,11 @@ static void _manifest_write_component(unsigned char **p, unsigned int *length, c node = plist_dict_get_item(comp, "Digest"); if (node) { - char *digest = NULL; uint64_t digest_len = 0; - plist_get_data_val(node, &digest, &digest_len); + const char *digest = plist_get_data_ptr(node, &digest_len); if (digest_len > 0) { - _manifest_write_key_value(&tmp, &tmp_len, "DGST", ASN1_OCTET_STRING, digest, digest_len); + _manifest_write_key_value(&tmp, &tmp_len, "DGST", ASN1_OCTET_STRING, (void*)digest, digest_len); } - free(digest); } node = plist_dict_get_item(comp, "Trusted"); @@ -740,9 +739,8 @@ static void _manifest_write_component(unsigned char **p, unsigned int *length, c node = plist_dict_get_item(comp, "TBMDigests"); if (node) { - char *data = NULL; uint64_t datalen = 0; - plist_get_data_val(node, &data, &datalen); + const char *data = plist_get_data_ptr(node, &datalen); const char *tbmtag = NULL; if (!strcmp(tag, "sepi")) { tbmtag = "tbms"; @@ -752,9 +750,8 @@ static void _manifest_write_component(unsigned char **p, unsigned int *length, c if (!tbmtag) { error("ERROR: Unexpected TMBDigests for comp '%s'\n", tag); } else { - _manifest_write_key_value(&tmp, &tmp_len, tbmtag, ASN1_OCTET_STRING, data, datalen); + _manifest_write_key_value(&tmp, &tmp_len, tbmtag, ASN1_OCTET_STRING, (void*)data, datalen); } - free(data); } asn1_write_element_header(ASN1_SET | ASN1_CONSTRUCTED, tmp_len, &inner_start, &inner_length); @@ -798,22 +795,22 @@ int img4_create_local_manifest(plist_t request, plist_t build_identity, plist_t* unsigned int tmp_len = 0; /* write manifest properties */ - uintval = _plist_dict_get_uint(request, "ApBoardID"); + uintval = plist_dict_get_uint(request, "ApBoardID"); _manifest_write_key_value(&tmp, &tmp_len, "BORD", ASN1_INTEGER, &uintval, -1); uintval = 0; _manifest_write_key_value(&tmp, &tmp_len, "CEPO", ASN1_INTEGER, &uintval, -1); - uintval = _plist_dict_get_uint(request, "ApChipID"); + uintval = plist_dict_get_uint(request, "ApChipID"); _manifest_write_key_value(&tmp, &tmp_len, "CHIP", ASN1_INTEGER, &uintval, -1); - boolval = _plist_dict_get_bool(request, "ApProductionMode"); + boolval = plist_dict_get_bool(request, "ApProductionMode"); _manifest_write_key_value(&tmp, &tmp_len, "CPRO", ASN1_BOOLEAN, &boolval, -1); boolval = 0; _manifest_write_key_value(&tmp, &tmp_len, "CSEC", ASN1_BOOLEAN, &boolval, -1); - uintval = _plist_dict_get_uint(request, "ApSecurityDomain"); + uintval = plist_dict_get_uint(request, "ApSecurityDomain"); _manifest_write_key_value(&tmp, &tmp_len, "SDOM", ASN1_INTEGER, &uintval, -1); /* create manifest properties set */ @@ -34,16 +34,8 @@ #include <sys/types.h> #include <dirent.h> #include <zip.h> -#ifdef HAVE_OPENSSL -#include <openssl/sha.h> -#else -#include "sha1.h" -#define SHA_CTX SHA1_CTX -#define SHA1_Init SHA1Init -#define SHA1_Update SHA1Update -#define SHA1_Final SHA1Final -#endif +#include <libimobiledevice-glue/sha.h> #include <libimobiledevice-glue/termcolors.h> #include <plist/plist.h> @@ -308,7 +300,7 @@ int ipsw_print_info(const char* path) ipsw_archive_t ipsw_open(const char* ipsw) { int err = 0; - ipsw_archive_t archive = (ipsw_archive_t)malloc(sizeof(struct ipsw_archive)); + ipsw_archive_t archive = (ipsw_archive_t)calloc(1, sizeof(struct ipsw_archive)); if (archive == NULL) { error("ERROR: Out of memory\n"); return NULL; @@ -320,14 +312,15 @@ ipsw_archive_t ipsw_open(const char* ipsw) return NULL; } if (S_ISDIR(fst.st_mode)) { - archive->zip = NULL; + archive->zip = 0; } else { - archive->zip = zip_open(ipsw, 0, &err); - if (archive->zip == NULL) { + struct zip *zip = zip_open(ipsw, 0, &err); + if (zip == NULL) { error("ERROR: zip_open: %s: %d\n", ipsw, err); free(archive); return NULL; } + archive->zip = 1; } archive->path = strdup(ipsw); return (ipsw_archive_t)archive; @@ -337,10 +330,6 @@ void ipsw_close(ipsw_archive_t ipsw) { if (ipsw != NULL) { free(ipsw->path); - if (ipsw->zip) { - zip_unchange_all(ipsw->zip); - zip_close(ipsw->zip); - } free(ipsw); } } @@ -363,18 +352,30 @@ int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size) } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { error("ERROR: zip_name_locate: %s\n", infile); + zip_unchange_all(zip); + zip_close(zip); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { error("ERROR: zip_stat_index: %s\n", infile); + zip_unchange_all(zip); + zip_close(zip); return -1; } + zip_unchange_all(zip); + zip_close(zip); *size = zstat.size; } else { @@ -404,35 +405,52 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, cancel_flag = 0; if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_name_locate: %s\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_stat_index: %s\n", infile); return -1; } char* buffer = (char*) malloc(BUFSIZE); if (buffer == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: Unable to allocate memory\n"); return -1; } - struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0); + struct zip_file* zfile = zip_fopen_index(zip, zindex, 0); if (zfile == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_fopen_index: %s\n", infile); return -1; } FILE* fd = fopen(outfile, "wb"); if (fd == NULL) { - error("ERROR: Unable to open output file: %s\n", outfile); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); + error("ERROR: Unable to open output file: %s\n", outfile); return -1; } @@ -447,7 +465,10 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, size = i; count = zip_fread(zfile, buffer, size); if (count < 0) { - error("ERROR: zip_fread: %s\n", infile); + int zep = 0; + int sep = 0; + zip_file_error_get(zfile, &zep, &sep); + error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep); ret = -1; break; } @@ -466,6 +487,8 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, free(buffer); fclose(fd); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); } else { char *filepath = build_path(ipsw->path, infile); char actual_filepath[PATH_MAX+1]; @@ -566,7 +589,15 @@ int ipsw_file_exists(ipsw_archive_t ipsw, const char* infile) } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return 0; + } + int zindex = zip_name_locate(zip, infile, 0); + zip_unchange_all(zip); + zip_close(zip); if (zindex < 0) { return 0; } @@ -592,21 +623,34 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { + zip_unchange_all(zip); + zip_close(zip); debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_stat_index: %s\n", infile); return -1; } - struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0); + struct zip_file* zfile = zip_fopen_index(zip, zindex, 0); if (zfile == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_fopen_index: %s\n", infile); return -1; } @@ -616,19 +660,29 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha if (buffer == NULL) { error("ERROR: Out of memory\n"); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); return -1; } - if (zip_fread(zfile, buffer, size) != size) { - error("ERROR: zip_fread: %s\n", infile); - zip_fclose(zfile); + zip_int64_t zr = zip_fread(zfile, buffer, size); + zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); + if (zr < 0) { + int zep = 0; + int sep = 0; + zip_file_error_get(zfile, &zep, &sep); + error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep); + free(buffer); + return -1; + } else if (zr != size) { + error("ERROR: zip_fread: %s got only %lld of %zu\n", infile, zr, size); free(buffer); return -1; } buffer[size] = '\0'; - - zip_fclose(zfile); } else { char *filepath = build_path(ipsw->path, infile); struct stat fst; @@ -699,21 +753,34 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { + zip_unchange_all(zip); + zip_close(zip); debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_stat_index: %s\n", infile); return -1; } - struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0); + struct zip_file* zfile = zip_fopen_index(zip, zindex, 0); if (zfile == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_fopen_index: %s\n", infile); return -1; } @@ -721,8 +788,10 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip total_size = zstat.size; buffer = (unsigned char*) malloc(blocksize); if (buffer == NULL) { - error("ERROR: Out of memory\n"); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); + error("ERROR: Out of memory\n"); return -1; } @@ -744,6 +813,9 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip done += zr; } free(buffer); + zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); } else { char *filepath = build_path(ipsw->path, infile); struct stat fst; @@ -926,7 +998,14 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx) } if (ipsw->zip) { - int64_t entries = zip_get_num_entries(ipsw->zip, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int64_t entries = zip_get_num_entries(zip, 0); if (entries < 0) { error("ERROR: zip_get_num_entries failed\n"); return -1; @@ -936,7 +1015,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx) zip_stat_t stat; zip_stat_init(&stat); - if (zip_stat_index(ipsw->zip, index, 0, &stat) < 0) { + if (zip_stat_index(zip, index, 0, &stat) < 0) { error("ERROR: zip_stat_index failed for %s\n", stat.name); ret = -1; continue; @@ -944,7 +1023,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx) uint8_t opsys; uint32_t attributes; - if (zip_file_get_external_attributes(ipsw->zip, index, 0, &opsys, &attributes) < 0) { + if (zip_file_get_external_attributes(zip, index, 0, &opsys, &attributes) < 0) { error("ERROR: zip_file_get_external_attributes failed for %s\n", stat.name); ret = -1; continue; @@ -1176,14 +1255,14 @@ static int sha1_verify_fp(FILE* f, unsigned char* expected_sha1) unsigned char tsha1[20]; char buf[8192]; if (!f) return 0; - SHA_CTX sha1ctx; - SHA1_Init(&sha1ctx); + sha1_context sha1ctx; + sha1_init(&sha1ctx); rewind(f); while (!feof(f)) { size_t sz = fread(buf, 1, 8192, f); - SHA1_Update(&sha1ctx, (const void*)buf, sz); + sha1_update(&sha1ctx, buf, sz); } - SHA1_Final(tsha1, &sha1ctx); + sha1_final(&sha1ctx, tsha1); return (memcmp(expected_sha1, tsha1, 20) == 0) ? 1 : 0; } @@ -1308,23 +1387,35 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path) { ipsw_file_handle_t handle = (ipsw_file_handle_t)calloc(1, sizeof(struct ipsw_file_handle)); if (ipsw->zip) { + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return NULL; + } + zip_stat_t zst; - zip_int64_t zindex = zip_name_locate(ipsw->zip, path, 0); + zip_int64_t zindex = zip_name_locate(zip, path, 0); if (zindex < 0) { error("ERROR: zip_name_locate: %s not found\n", path); + zip_unchange_all(zip); + zip_close(zip); free(handle); return NULL; } - handle->zfile = zip_fopen_index(ipsw->zip, zindex, 0); + handle->zfile = zip_fopen_index(zip, zindex, 0); if (handle->zfile == NULL) { error("ERROR: zip_fopen_index: %s could not be opened\n", path); + zip_unchange_all(zip); + zip_close(zip); free(handle); return NULL; } zip_stat_init(&zst); - zip_stat(ipsw->zip, path, 0, &zst); + zip_stat(zip, path, 0, &zst); handle->size = zst.size; handle->seekable = (zst.comp_method == ZIP_CM_STORE); + handle->zip = zip; } else { struct stat st; char *filepath = build_path(ipsw->path, path); @@ -1346,6 +1437,8 @@ void ipsw_file_close(ipsw_file_handle_t handle) { if (handle && handle->zfile) { zip_fclose(handle->zfile); + zip_unchange_all(handle->zip); + zip_close(handle->zip); } else if (handle && handle->file) { fclose(handle->file); } @@ -33,7 +33,7 @@ extern "C" { #include <sys/stat.h> struct ipsw_archive { - struct zip* zip; + int zip; char *path; }; typedef struct ipsw_archive* ipsw_archive_t; @@ -48,6 +48,7 @@ typedef int (*ipsw_send_cb)(void *ctx, void *data, size_t size, size_t done, siz struct ipsw_file_handle { FILE* file; + struct zip* zip; struct zip_file* zfile; uint64_t size; int seekable; diff --git a/src/normal.c b/src/normal.c index efe8f03..e699bbe 100644 --- a/src/normal.c +++ b/src/normal.c @@ -462,13 +462,13 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_ } else { plist_t node; - if (_plist_dict_get_bool(pl, "Skip")) { + if (plist_dict_get_bool(pl, "Skip")) { result = 0; info("Device does not require stashbag.\n"); break; } - if (_plist_dict_get_bool(pl, "ShowDialog")) { + if (plist_dict_get_bool(pl, "ShowDialog")) { info("Device requires stashbag.\n"); printf("******************************************************************************\n" "* Please enter your passcode on the device. The device will store a token *\n" @@ -491,13 +491,13 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_ plist_free(pl); break; } - if (_plist_dict_get_bool(pl, "Timeout")) { + if (plist_dict_get_bool(pl, "Timeout")) { error("ERROR: Timeout while waiting for user to enter passcode.\n"); result = -2; plist_free(pl); break; } - if (_plist_dict_get_bool(pl, "HideDialog")) { + if (plist_dict_get_bool(pl, "HideDialog")) { plist_free(pl); /* hide dialog */ result = 1; @@ -588,7 +588,7 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_ } error("ERROR: Could not commit stashbag: %s\n", (strval) ? strval : "(Unknown error)"); free(strval); - } else if (_plist_dict_get_bool(pl, "StashbagCommitComplete")) { + } else if (plist_dict_get_bool(pl, "StashbagCommitComplete")) { info("Stashbag committed!\n"); result = 0; } else { diff --git a/src/recovery.c b/src/recovery.c index e3fb4d1..afda4a9 100644 --- a/src/recovery.c +++ b/src/recovery.c @@ -29,8 +29,9 @@ #include <libimobiledevice/restore.h> #include <libimobiledevice/libimobiledevice.h> +#include <libtatsu/tss.h> + #include "idevicerestore.h" -#include "tss.h" #include "img3.h" #include "restore.h" #include "recovery.h" diff --git a/src/restore.c b/src/restore.c index 1261147..d3828f9 100644 --- a/src/restore.c +++ b/src/restore.c @@ -31,6 +31,8 @@ #include <unistd.h> #include <libgen.h> #include <libimobiledevice/restore.h> +#include <libimobiledevice/property_list_service.h> +#include <libimobiledevice-glue/thread.h> #ifdef HAVE_REVERSE_PROXY #include <libimobiledevice/reverse_proxy.h> #else @@ -38,6 +40,8 @@ #endif #include <zip.h> #include <libirecovery.h> +#include <libtatsu/tss.h> +#include <curl/curl.h> #include "idevicerestore.h" #include "asr.h" @@ -45,7 +49,6 @@ #include "fls.h" #include "mbn.h" #include "ftab.h" -#include "tss.h" #include "ipsw.h" #include "restore.h" #include "common.h" @@ -633,6 +636,101 @@ const char* restore_progress_string(unsigned int operation) } } +struct restored_service_client { + +}; + +#define SERVICE_TYPE_RESTORED 1 +#define SERVICE_TYPE_PLIST 2 + +typedef struct restore_service_client { + void* client; + int type; +} *restore_service_client_t; + +static void* _restore_get_service_client_for_data_request(struct idevicerestore_client_t *client, plist_t message) +{ + if (!client || !client->restore || !client->restore->client || !PLIST_IS_DICT(message)) return NULL; + restore_service_client_t service = (restore_service_client_t)malloc(sizeof(struct restore_service_client)); + if (!plist_dict_get_item(message, "DataPort")) { + service->client = client->restore->client; + service->type = SERVICE_TYPE_RESTORED; + return service; + } + plist_t data_type = plist_dict_get_item(message, "DataType"); + uint16_t data_port = plist_dict_get_uint(message, "DataPort"); + const char* data_type_str = plist_get_string_ptr(data_type, NULL); + + struct lockdownd_service_descriptor svcdesc = { + data_port, + 0, + (char*)data_type_str + }; + property_list_service_client_t plclient = NULL; + info("Connecting to %s data port %u\n", data_type_str, data_port); + if (property_list_service_client_new(client->restore->device, &svcdesc, &plclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { + error("ERROR: Failed to start service connection for %s on port %u\n", data_type_str, data_port); + free(service); + return NULL; + } + service->client = plclient; + service->type = SERVICE_TYPE_PLIST; + + return service; +} + +static int _restore_service_send(restore_service_client_t service, plist_t plist, plist_format_t fmt) +{ + if (!service) { + return -1; + } + switch (service->type) { + case SERVICE_TYPE_RESTORED: + return restored_send((restored_client_t)service->client, plist); + case SERVICE_TYPE_PLIST: + if (fmt == PLIST_FORMAT_BINARY) { + return property_list_service_send_binary_plist((property_list_service_client_t)service->client, plist); + } + return property_list_service_send_xml_plist((property_list_service_client_t)service->client, plist); + default: + break; + } + return -1; +} + +static int _restore_service_recv(restore_service_client_t service, plist_t *plist) +{ + if (!service) { + return -1; + } + switch (service->type) { + case SERVICE_TYPE_RESTORED: + return restored_receive((restored_client_t)service->client, plist); + case SERVICE_TYPE_PLIST: + return property_list_service_receive_plist((property_list_service_client_t)service->client, plist); + default: + break; + } + return -1; +} + +static void _restore_service_free(restore_service_client_t service) +{ + if (!service) { + return; + } + switch (service->type) { + case SERVICE_TYPE_RESTORED: + break; + case SERVICE_TYPE_PLIST: + property_list_service_client_free((property_list_service_client_t)service->client); + break; + default: + break; + } + free(service); +} + static int lastop = 0; static int restore_handle_previous_restore_log_msg(restored_client_t client, plist_t msg) @@ -686,6 +784,9 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t info("%s (%d)\n", restore_progress_string(adapted_operation), (int)operation); } switch (adapted_operation) { + case RESTORE_IMAGE: + idevicerestore_progress(client, RESTORE_STEP_UPLOAD_FS, progress / 100.0); + break; case VERIFY_RESTORE: idevicerestore_progress(client, RESTORE_STEP_VERIFY_FS, progress / 100.0); break; @@ -715,7 +816,7 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t return 0; } -int restore_handle_status_msg(restored_client_t client, plist_t msg) +int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t msg) { int result = 0; uint64_t value = 0; @@ -781,10 +882,10 @@ int restore_handle_status_msg(restored_client_t client, plist_t msg) return result; } -static int restore_handle_baseband_updater_output_data(restored_client_t restore, struct idevicerestore_client_t* client, idevice_t device, plist_t msg) +static int restore_handle_baseband_updater_output_data(struct idevicerestore_client_t* client, plist_t message) { int result = -1; - plist_t node = plist_dict_get_item(msg, "DataPort"); + plist_t node = plist_dict_get_item(message, "DataPort"); uint64_t u64val = 0; plist_get_uint_val(node, &u64val); uint16_t data_port = (uint16_t)u64val; @@ -793,9 +894,14 @@ static int restore_handle_baseband_updater_output_data(restored_client_t restore idevice_connection_t connection = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; + if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + debug("Connecting to baseband updater data port\n"); while (--attempts > 0) { - device_error = idevice_connect(device, data_port, &connection); + device_error = idevice_connect(client->restore->device, data_port, &connection); if (device_error == IDEVICE_E_SUCCESS) { break; } @@ -850,10 +956,10 @@ static int restore_handle_baseband_updater_output_data(restored_client_t restore return result; } -static int restore_handle_bb_update_status_msg(restored_client_t client, plist_t msg) +static int restore_handle_bb_update_status_msg(struct idevicerestore_client_t* client, plist_t message) { int result = -1; - plist_t node = plist_dict_get_item(msg, "Accepted"); + plist_t node = plist_dict_get_item(message, "Accepted"); uint8_t accepted = 0; plist_get_bool_val(node, &accepted); @@ -863,14 +969,14 @@ static int restore_handle_bb_update_status_msg(restored_client_t client, plist_t } uint8_t done = 0; - node = plist_access_path(msg, 2, "Output", "done"); + node = plist_access_path(message, 2, "Output", "done"); if (node && plist_get_node_type(node) == PLIST_BOOLEAN) { plist_get_bool_val(node, &done); } if (done) { info("Updating Baseband completed.\n"); - plist_t provisioning = plist_access_path(msg, 2, "Output", "provisioning"); + plist_t provisioning = plist_access_path(message, 2, "Output", "provisioning"); if (provisioning && plist_get_node_type(provisioning) == PLIST_DICT) { char* sval = NULL; node = plist_dict_get_item(provisioning, "IMEI"); @@ -898,16 +1004,21 @@ static void restore_asr_progress_cb(double progress, void* userdata) } } -int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, plist_t build_identity) +int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t message) { asr_client_t asr = NULL; - - info("About to send filesystem...\n"); - ipsw_archive_t ipsw_dummy = NULL; ipsw_file_handle_t file = NULL; char* fsname = NULL; - if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) { + + if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + + info("About to send filesystem...\n"); + + if (build_identity_get_component_path(client->restore->build_identity, "OS", &fsname) < 0) { error("ERROR: Unable to get path for filesystem component\n"); return -1; } @@ -926,7 +1037,11 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de free(fsname); } - if (asr_open_with_timeout(device, &asr) < 0) { + uint16_t asr_port = (uint16_t)plist_dict_get_uint(message, "DataPort"); + if (asr_port == 0) { + asr_port = ASR_DEFAULT_PORT; + } + if (asr_open_with_timeout(client->restore->device, &asr, asr_port) < 0) { ipsw_file_close(file); ipsw_close(ipsw_dummy); error("ERROR: Unable to connect to ASR\n"); @@ -934,7 +1049,9 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de } info("Connected to ASR\n"); - asr_set_progress_callback(asr, restore_asr_progress_cb, (void*)client); + if (asr_port == ASR_DEFAULT_PORT) { + asr_set_progress_callback(asr, restore_asr_progress_cb, (void*)client); + } // this step sends requested chunks of data from various offsets to asr so // it can validate the filesystem before installing it @@ -967,7 +1084,7 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de return 0; } -int restore_send_recovery_os_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client) +int restore_send_recovery_os_root_ticket(struct idevicerestore_client_t* client, plist_t message) { restored_error_t restore_error; plist_t dict; @@ -1007,9 +1124,16 @@ int restore_send_recovery_os_root_ticket(restored_client_t restore, struct idevi free(data); } + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending RecoveryOSRootTicket now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to send RootTicket (%d)\n", restore_error); return -1; @@ -1020,7 +1144,7 @@ int restore_send_recovery_os_root_ticket(restored_client_t restore, struct idevi } -int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client) +int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t message) { restored_error_t restore_error; plist_t dict; @@ -1060,9 +1184,16 @@ int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_cl free(data); } + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending RootTicket now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to send RootTicket (%d)\n", restore_error); return -1; @@ -1072,7 +1203,246 @@ int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_cl return 0; } -int restore_send_component(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* component_name) +typedef struct { + int length; + char* content; +} query_response; + +static size_t _curl_write_callback(char* data, size_t size, size_t nmemb, query_response* response) +{ + size_t total = size * nmemb; + if (total != 0) { + response->content = realloc(response->content, response->length + total + 1); + memcpy(response->content + response->length, data, total); + response->content[response->length + total] = '\0'; + response->length += total; + } + + return total; +} + +static size_t _curl_header_callback(char* buffer, size_t size, size_t nitems, void* userdata) +{ + plist_t header_dict = (plist_t)userdata; + size_t len = nitems*size; + char* key = NULL; + char* val = NULL; + size_t i = 0; + while (i < len) { + if (buffer[i] == ':') { + key = malloc(i+1); + strncpy(key, buffer, i); + key[i] = '\0'; + i++; + while (i < len && buffer[i] == ' ' || buffer[i] == '\t') i++; + val = malloc(len-i+1); + strncpy(val, buffer+i, len-i); + val[len-i] = '\0'; + break; + } + i++; + } + if (key && val) { + plist_dict_set_item(header_dict, key, plist_new_string(val)); + } + free(key); + free(val); + return len; +} + +int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t message) +{ + debug("DEBUG: %s\n", __func__); + plist_t arguments = plist_dict_get_item(message, "Arguments"); + if (!PLIST_IS_DICT(arguments)) { + error("ERROR: %s: Unexpected arguments\n", __func__); + debug_plist(arguments); + return -1; + } + + const char* request_method = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestMethod"), NULL); + if (!request_method) { + error("ERROR: %s: Unable to extract RequestMethod from Arguments\n", __func__); + return -1; + } + if (strcmp(request_method, "GET")) { + error("ERROR: %s: Unexpected RequestMethod '%s' in message\n", __func__, request_method); + return -1; + } + const char* request_url = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestURL"), NULL); + if (!request_url) { + error("ERROR: %s: Unable to extract RequestURL from Arguments\n", __func__); + return -1; + } + info("Requesting URLAsset from %s\n", request_url); + + char curl_error_message[CURL_ERROR_SIZE]; + CURL* handle = curl_easy_init(); + /* disable SSL verification to allow download from untrusted https locations */ + curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); + + query_response* response = malloc(sizeof(query_response)); + if (response == NULL) { + error("ERROR: %s: Unable to allocate sufficient memory\n", __func__); + return -1; + } + + response->length = 0; + response->content = malloc(1); + response->content[0] = '\0'; + + curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&_curl_write_callback); + curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, &_curl_header_callback); + plist_t response_headers = plist_new_dict(); + curl_easy_setopt(handle, CURLOPT_HEADERDATA, response_headers); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); + if (idevicerestore_debug) { + curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); + } + curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(handle, CURLOPT_URL, request_url); + curl_easy_perform(handle); + + long http_response = 0; + curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_response); + + curl_easy_cleanup(handle); + + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "ResponseBody", plist_new_data(response->content, response->length)); + plist_dict_set_item(dict, "ResponseBodyDone", plist_new_bool(1)); + plist_dict_set_item(dict, "ResponseHeaders", response_headers); + plist_dict_set_item(dict, "ResponseStatus", plist_new_uint(http_response)); + + free(response); + + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + + _restore_service_send(service, dict, PLIST_FORMAT_BINARY); + _restore_service_free(service); + + return 0; +} + +int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* client, plist_t message) +{ + debug("DEBUG: %s\n", __func__); + plist_t arguments = plist_dict_get_item(message, "Arguments"); + if (!PLIST_IS_DICT(arguments)) { + error("ERROR: %s: Unexpected arguments\n", __func__); + debug_plist(arguments); + return -1; + } + + const char* request_method = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestMethod"), NULL); + if (!request_method) { + error("ERROR: %s: Unable to extract RequestMethod from Arguments\n", __func__); + return -1; + } + if (strcmp(request_method, "POST")) { + error("ERROR: %s: Unexpected RequestMethod '%s' in message\n", __func__, request_method); + return -1; + } + const char* request_url = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestURL"), NULL); + if (!request_url) { + error("ERROR: %s: Unable to extract RequestURL from Arguments\n", __func__); + return -1; + } + + struct curl_slist* header = NULL; + + plist_t headers = plist_dict_get_item(arguments, "RequestAdditionalHeaders"); + if (!headers) { + error("ERROR: %s: Missing 'RequestAdditionalHeaders'\n", __func__); + return -1; + } + + uint64_t request_body_size = 0; + const char* request_body = plist_get_data_ptr(plist_dict_get_item(arguments, "RequestBody"), &request_body_size); + if (!request_body) { + error("ERROR: %s: Missing 'RequestBody'\n", __func__); + return -1; + } + + info("Requesting image decryption key from %s\n", request_url); + + char curl_error_message[CURL_ERROR_SIZE]; + char header_tmp[1024]; + plist_dict_iter iter = NULL; + plist_dict_new_iter(headers, &iter); + plist_t node = NULL; + do { + char *key = NULL; + plist_dict_next_item(headers, iter, &key, &node); + if (!node) break; + snprintf(header_tmp, sizeof(header_tmp), "%s: %s", key, plist_get_string_ptr(node, NULL)); + curl_slist_append(header, header_tmp); + } while (node); + plist_mem_free(iter); + + CURL* handle = curl_easy_init(); + /* disable SSL verification to allow download from untrusted https locations */ + curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); + + query_response* response = malloc(sizeof(query_response)); + if (response == NULL) { + error("ERROR: %s: Unable to allocate sufficient memory\n", __func__); + return -1; + } + + response->length = 0; + response->content = malloc(1); + response->content[0] = '\0'; + + curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&_curl_write_callback); + curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, &_curl_header_callback); + plist_t response_headers = plist_new_dict(); + curl_easy_setopt(handle, CURLOPT_HEADERDATA, response_headers); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); + curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request_body); + curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, request_body_size); + if (idevicerestore_debug) { + curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); + } + curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(handle, CURLOPT_URL, request_url); + curl_easy_perform(handle); + curl_slist_free_all(header); + + long http_response = 0; + curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_response); + + curl_easy_cleanup(handle); + + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "ResponseBody", plist_new_data(response->content, response->length)); + plist_dict_set_item(dict, "ResponseBodyDone", plist_new_bool(1)); + plist_dict_set_item(dict, "ResponseHeaders", response_headers); + plist_dict_set_item(dict, "ResponseStatus", plist_new_uint(http_response)); + + free(response); + + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + + _restore_service_send(service, dict, PLIST_FORMAT_BINARY); + _restore_service_free(service); + + return 0; +} + +int restore_send_component(struct idevicerestore_client_t* client, plist_t message, const char* component, const char* component_name) { unsigned int size = 0; unsigned char* data = NULL; @@ -1081,6 +1451,11 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie plist_t dict = NULL; restored_error_t restore_error = RESTORE_E_SUCCESS; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + if (component_name == NULL) { component_name = component; } @@ -1093,7 +1468,7 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie } } if (!path) { - if (build_identity_get_component_path(build_identity, component, &path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, component, &path) < 0) { error("ERROR: Unable to find %s path from build identity\n", component); return -1; } @@ -1124,9 +1499,16 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie plist_dict_set_item(dict, compkeyname, blob); free(data); + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending %s now...\n", component_name); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to send component %s data\n", component_name); return -1; @@ -1136,7 +1518,7 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie return 0; } -int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) +int restore_send_nor(struct idevicerestore_client_t* client, plist_t message) { char* llb_path = NULL; char* llb_filename = NULL; @@ -1156,6 +1538,11 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* plist_t firmware_files = NULL; int flash_version_1 = 0; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + info("About to send NORData...\n"); plist_t arguments = plist_dict_get_item(message, "Arguments"); @@ -1169,7 +1556,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* } } if (llb_path == NULL) { - if (build_identity_get_component_path(build_identity, "LLB", &llb_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, "LLB", &llb_path) < 0) { error("ERROR: Unable to get component path for LLB\n"); return -1; } @@ -1209,7 +1596,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* } else { info("Getting firmware manifest from build identity\n"); plist_dict_iter iter = NULL; - plist_t build_id_manifest = plist_dict_get_item(build_identity, "Manifest"); + plist_t build_id_manifest = plist_dict_get_item(client->restore->build_identity, "Manifest"); if (build_id_manifest) { plist_dict_new_iter(build_id_manifest, &iter); } @@ -1279,7 +1666,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* } dict = plist_new_dict(); - plist_dict_set_item(dict, "LlbImageData", plist_new_data((char*)llb_data, (uint64_t) llb_size)); + plist_dict_set_item(dict, "LlbImageData", plist_new_data((char*)llb_data, llb_size)); free(llb_data); if (flash_version_1) { @@ -1339,13 +1726,13 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* component_size = 0; if (flash_version_1) { - plist_dict_set_item(norimage, component, plist_new_data((char*)nor_data, (uint64_t)nor_size)); + plist_dict_set_item(norimage, component, plist_new_data((char*)nor_data, nor_size)); } else { /* make sure iBoot is the first entry in the array */ if (!strncmp("iBoot", component, 5)) { - plist_array_insert_item(norimage, plist_new_data((char*)nor_data, (uint64_t)nor_size), 0); + plist_array_insert_item(norimage, plist_new_data((char*)nor_data, nor_size), 0); } else { - plist_array_append_item(norimage, plist_new_data((char*)nor_data, (uint64_t)nor_size)); + plist_array_append_item(norimage, plist_new_data((char*)nor_data, nor_size)); } } @@ -1362,8 +1749,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* unsigned char* personalized_data = NULL; unsigned int personalized_size = 0; - if (build_identity_has_component(build_identity, "RestoreSEP") && - build_identity_get_component_path(build_identity, "RestoreSEP", &restore_sep_path) == 0) { + if (build_identity_has_component(client->restore->build_identity, "RestoreSEP") && + build_identity_get_component_path(client->restore->build_identity, "RestoreSEP", &restore_sep_path) == 0) { component = "RestoreSEP"; ret = extract_component(client->ipsw, restore_sep_path, &component_data, &component_size); free(restore_sep_path); @@ -1381,14 +1768,14 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* return -1; } - plist_dict_set_item(dict, "RestoreSEPImageData", plist_new_data((char*)personalized_data, (uint64_t) personalized_size)); + plist_dict_set_item(dict, "RestoreSEPImageData", plist_new_data((char*)personalized_data, personalized_size)); free(personalized_data); personalized_data = NULL; personalized_size = 0; } - if (build_identity_has_component(build_identity, "SEP") && - build_identity_get_component_path(build_identity, "SEP", &sep_path) == 0) { + if (build_identity_has_component(client->restore->build_identity, "SEP") && + build_identity_get_component_path(client->restore->build_identity, "SEP", &sep_path) == 0) { component = "SEP"; ret = extract_component(client->ipsw, sep_path, &component_data, &component_size); free(sep_path); @@ -1406,14 +1793,14 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* return -1; } - plist_dict_set_item(dict, "SEPImageData", plist_new_data((char*)personalized_data, (uint64_t) personalized_size)); + plist_dict_set_item(dict, "SEPImageData", plist_new_data((char*)personalized_data, personalized_size)); free(personalized_data); personalized_data = NULL; personalized_size = 0; } - if (build_identity_has_component(build_identity, "SepStage1") && - build_identity_get_component_path(build_identity, "SepStage1", &sep_path) == 0) { + if (build_identity_has_component(client->restore->build_identity, "SepStage1") && + build_identity_get_component_path(client->restore->build_identity, "SepStage1", &sep_path) == 0) { component = "SepStage1"; ret = extract_component(client->ipsw, sep_path, &component_data, &component_size); free(sep_path); @@ -1431,7 +1818,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* return -1; } - plist_dict_set_item(dict, "SEPPatchImageData", plist_new_data((char*)personalized_data, (uint64_t) personalized_size)); + plist_dict_set_item(dict, "SEPPatchImageData", plist_new_data((char*)personalized_data, personalized_size)); free(personalized_data); personalized_data = NULL; personalized_size = 0; @@ -1440,15 +1827,22 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* if (idevicerestore_debug) debug_plist(dict); + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending NORData now...\n"); - if (restored_send(restore, dict) != RESTORE_E_SUCCESS) { + restored_error_t restore_error = _restore_service_send(service, dict, 0); + plist_free(dict); + _restore_service_free(service); + if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to send NORData\n"); - plist_free(dict); return -1; } info("Done sending NORData\n"); - plist_free(dict); return 0; } @@ -1510,7 +1904,7 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned } unsigned char* buffer = NULL; - unsigned char* blob = NULL; + const unsigned char* blob = NULL; unsigned char* fdata = NULL; uint64_t fsize = 0; uint64_t blob_size = 0; @@ -1607,9 +2001,8 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned free(buffer); buffer = NULL; - blob = NULL; blob_size = 0; - plist_get_data_val(node, (char**)&blob, &blob_size); + blob = (const unsigned char*)plist_get_data_ptr(node, &blob_size); if (!blob) { error("ERROR: could not get %s-Blob data\n", key); goto leave; @@ -1626,8 +2019,6 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned goto leave; } } - free(blob); - blob = NULL; fsize = (is_fls ? fls->size : mbn->size); fdata = (unsigned char*)malloc(fsize); @@ -1740,9 +2131,8 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned goto leave; } - blob = NULL; blob_size = 0; - plist_get_data_val(bbticket, (char**)&blob, &blob_size); + blob = (const unsigned char*)plist_get_data_ptr(bbticket, &blob_size); if (!blob) { error("ERROR: could not get BBTicket data\n"); goto leave; @@ -1752,8 +2142,6 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned error("ERROR: could not insert BBTicket to ebl.fls\n"); goto leave; } - free(blob); - blob = NULL; fsize = fls->size; fdata = (unsigned char*)malloc(fsize); @@ -1778,20 +2166,18 @@ static int restore_sign_bbfw(const char* bbfwtmp, plist_t bbtss, const unsigned } } else { // add BBTicket as bbticket.der - blob = NULL; blob_size = 0; - plist_get_data_val(bbticket, (char**)&blob, &blob_size); + blob = (const unsigned char*)plist_get_data_ptr(bbticket, &blob_size); if (!blob) { error("ERROR: could not get BBTicket data\n"); goto leave; } - zs = zip_source_buffer(za, blob, blob_size, 1); + zs = zip_source_buffer(za, blob, blob_size, 0); if (!zs) { error("ERROR: out of memory\n"); goto leave; } - blob = NULL; if (zip_file_add(za, "bbticket.der", zs, ZIP_FL_OVERWRITE) == -1) { error("ERROR: could not add bbticket.der to archive\n"); @@ -1824,12 +2210,11 @@ leave: mbn_free(mbn); fls_free(fls); free(buffer); - free(blob); return res; } -static int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) +static int restore_send_baseband_data(struct idevicerestore_client_t* client, plist_t message) { int res = -1; uint64_t bb_cert_id = 0; @@ -1843,6 +2228,11 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer char* bbfwtmp = NULL; plist_t dict = NULL; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + info("About to send BasebandData...\n"); // NOTE: this function is called 2 or 3 times! @@ -1879,7 +2269,7 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer plist_dict_set_item(parameters, "BbGoldCertId", plist_new_uint(bb_cert_id)); plist_dict_set_item(parameters, "BbSNUM", plist_new_data((const char*)bb_snum, bb_snum_size)); - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); /* create baseband request */ plist_t request = tss_request_new(NULL); @@ -1893,7 +2283,7 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer tss_request_add_common_tags(request, parameters, NULL); tss_request_add_baseband_tags(request, parameters, NULL); - plist_t node = plist_access_path(build_identity, 2, "Info", "FDRSupport"); + plist_t node = plist_access_path(client->restore->build_identity, 2, "Info", "FDRSupport"); if (node && plist_get_node_type(node) == PLIST_BOOLEAN) { uint8_t b = 0; plist_get_bool_val(node, &b); @@ -1920,7 +2310,7 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer } // get baseband firmware file path from build identity - plist_t bbfw_path = plist_access_path(build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path"); + plist_t bbfw_path = plist_access_path(client->restore->build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path"); if (!bbfw_path || plist_get_node_type(bbfw_path) != PLIST_STRING) { error("ERROR: Unable to get BasebandFirmware/Info/Path node\n"); plist_free(response); @@ -1970,16 +2360,24 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer // send file dict = plist_new_dict(); - plist_dict_set_item(dict, "BasebandData", plist_new_data(buffer, (uint64_t)sz)); + plist_dict_set_item(dict, "BasebandData", plist_new_data(buffer, sz)); free(buffer); buffer = NULL; + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending BasebandData now...\n"); - if (restored_send(restore, dict) != RESTORE_E_SUCCESS) { + if (_restore_service_send(service, dict, 0) != RESTORE_E_SUCCESS) { error("ERROR: Unable to send BasebandData data\n"); goto leave; } + _restore_service_free(service); + info("Done sending BasebandData\n"); res = 0; @@ -1995,7 +2393,7 @@ leave: return res; } -int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device) +int restore_send_fdr_trust_data(struct idevicerestore_client_t* client, plist_t message) { restored_error_t restore_error; plist_t dict; @@ -2007,9 +2405,16 @@ int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device) * and this is what iTunes seems to be doing too */ dict = plist_new_dict(); + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending FDR Trust data now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: During sending FDR Trust data (%d)\n", restore_error); return -1; @@ -2020,7 +2425,7 @@ int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device) return 0; } -static int restore_send_image_data(restored_client_t restore, struct idevicerestore_client_t *client, plist_t build_identity, plist_t message, const char *image_list_k, const char *image_type_k, const char *image_data_k) +static int restore_send_image_data(struct idevicerestore_client_t *client, plist_t message, const char *image_list_k, const char *image_type_k, const char *image_data_k) { restored_error_t restore_error; plist_t arguments; @@ -2033,8 +2438,13 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest char *image_name = NULL; int want_image_list = 0; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + arguments = plist_dict_get_item(message, "Arguments"); - want_image_list = _plist_dict_get_bool(arguments, image_list_k); + want_image_list = plist_dict_get_bool(arguments, image_list_k); node = plist_dict_get_item(arguments, "ImageName"); if (node) { plist_get_string_val(node, &image_name); @@ -2060,7 +2470,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest data_dict = plist_new_dict(); } - build_id_manifest = plist_dict_get_item(build_identity, "Manifest"); + build_id_manifest = plist_dict_get_item(client->restore->build_identity, "Manifest"); if (build_id_manifest) { plist_dict_new_iter(build_id_manifest, &iter); } @@ -2092,7 +2502,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest if (!image_name) { info("Found %s component '%s'\n", image_type_k, component); } - build_identity_get_component_path(build_identity, component, &path); + build_identity_get_component_path(client->restore->build_identity, component, &path); if (path) { ret = extract_component(client->ipsw, path, &component_data, &component_size); } @@ -2119,6 +2529,12 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest free(iter); } + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + dict = plist_new_dict(); if (want_image_list) { plist_dict_set_item(dict, image_list_k, matched_images); @@ -2137,8 +2553,9 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest } } - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { if (want_image_list) { error("ERROR: Failed to send %s image list (%d)\n", image_type_k, restore_error); @@ -2164,7 +2581,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest return 0; } -static plist_t restore_get_se_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) +static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { const char *comp_name = NULL; char *comp_path = NULL; @@ -2176,6 +2593,12 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id plist_t p_dgr = NULL; int ret; uint64_t chip_id = 0; + + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + plist_t node = plist_dict_get_item(p_info, "SE,ChipID"); if (node && plist_get_node_type(node) == PLIST_UINT) { plist_get_uint_val(node, &chip_id); @@ -2186,9 +2609,9 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id comp_name = "SE,UpdatePayload"; } else { info("WARNING: Unknown SE,ChipID 0x%" PRIx64 " detected. Restore might fail.\n", (uint64_t)chip_id); - if (build_identity_has_component(build_identity, "SE,UpdatePayload")) + if (build_identity_has_component(client->restore->build_identity, "SE,UpdatePayload")) comp_name = "SE,UpdatePayload"; - else if (build_identity_has_component(build_identity, "SE,Firmware")) + else if (build_identity_has_component(client->restore->build_identity, "SE,Firmware")) comp_name = "SE,Firmware"; else { error("ERROR: Neither 'SE,Firmware' nor 'SE,UpdatePayload' found in build identity.\n"); @@ -2205,7 +2628,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id return NULL; } - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; } @@ -2229,7 +2652,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); /* add SE,* tags from info dictionary to parameters */ plist_dict_merge(¶meters, p_info); @@ -2256,7 +2679,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id error("ERROR: No 'SE ticket' in TSS response, this might not work\n"); } - plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, (uint64_t) component_size)); + plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, component_size)); free(component_data); component_data = NULL; component_size = 0; @@ -2264,7 +2687,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id return response; } -static plist_t restore_get_savage_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = NULL; char *comp_path = NULL; @@ -2276,6 +2699,17 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc plist_t response = NULL; int ret; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Savage request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2286,13 +2720,13 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); /* add Savage,* tags from info dictionary to parameters */ plist_dict_merge(¶meters, p_info); /* add required tags for Savage TSS request */ - tss_request_add_savage_tags(request, parameters, NULL, &comp_name); + tss_request_add_savage_tags(request, parameters, device_generated_request, &comp_name); plist_free(parameters); @@ -2319,7 +2753,7 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc } /* now get actual component data */ - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); free(comp_name); return NULL; @@ -2347,7 +2781,7 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc *(uint32_t*)(component_data + 4) = htole32((uint32_t)component_size); component_size += 16; - plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, (uint64_t) component_size)); + plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, component_size)); free(component_data); component_data = NULL; component_size = 0; @@ -2355,7 +2789,7 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc return response; } -static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = NULL; char *comp_path = NULL; @@ -2366,6 +2800,17 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru plist_t response = NULL; int ret; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Yonkers request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2378,13 +2823,13 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); /* add Yonkers,* tags from info dictionary to parameters */ plist_dict_merge(¶meters, p_info); /* add required tags for Yonkers TSS request */ - tss_request_add_yonkers_tags(request, parameters, NULL, &comp_name); + tss_request_add_yonkers_tags(request, parameters, device_generated_request, &comp_name); plist_free(parameters); @@ -2410,7 +2855,7 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru error("ERROR: No 'Yonkers,Ticket' in TSS response, this might not work\n"); } - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); free(comp_name); return NULL; @@ -2429,7 +2874,7 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru comp_name = NULL; plist_t firmware_data = plist_new_dict(); - plist_dict_set_item(firmware_data, "YonkersFirmware", plist_new_data((char *)component_data, (uint64_t)component_size)); + plist_dict_set_item(firmware_data, "YonkersFirmware", plist_new_data((char*)component_data, component_size)); plist_dict_set_item(response, "FirmwareData", firmware_data); free(component_data); @@ -2439,7 +2884,7 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru return response; } -static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) +static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = NULL; char *comp_path = NULL; @@ -2453,6 +2898,11 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct plist_t response = NULL; int ret; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + /* create Rose request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2464,7 +2914,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1)); if (client->image4supported) { @@ -2510,7 +2960,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct } comp_name = "Rap,RTKitOS"; - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; } @@ -2534,8 +2984,8 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct } comp_name = "Rap,RestoreRTKitOS"; - if (build_identity_has_component(build_identity, comp_name)) { - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_has_component(client->restore->build_identity, comp_name)) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { ftab_free(ftab); error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; @@ -2578,7 +3028,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct ftab_write(ftab, &component_data, &component_size); ftab_free(ftab); - plist_dict_set_item(response, "FirmwareData", plist_new_data((char *)component_data, (uint64_t)component_size)); + plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, component_size)); free(component_data); component_data = NULL; component_size = 0; @@ -2586,7 +3036,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct return response; } -static plist_t restore_get_veridian_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = "BMU,FirmwareMap"; char *comp_path = NULL; @@ -2597,6 +3047,17 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str plist_t response = NULL; int ret; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Veridian request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2608,13 +3069,13 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); /* add BMU,* tags from info dictionary to parameters */ plist_dict_merge(¶meters, p_info); /* add required tags for Veridian TSS request */ - tss_request_add_veridian_tags(request, parameters, NULL); + tss_request_add_veridian_tags(request, parameters, device_generated_request); plist_free(parameters); @@ -2633,7 +3094,7 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str error("ERROR: No 'BMU,Ticket' in TSS response, this might not work\n"); } - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; } @@ -2662,7 +3123,7 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str return NULL; } - plist_t fw_map_digest = plist_access_path(build_identity, 3, "Manifest", comp_name, "Digest"); + plist_t fw_map_digest = plist_access_path(client->restore->build_identity, 3, "Manifest", comp_name, "Digest"); if (!fw_map_digest) { plist_free(fw_map); error("ERROR: Unable to get Digest for '%s' component\n", comp_name); @@ -2676,13 +3137,13 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str plist_to_bin(fw_map, &bin_plist, &bin_size); plist_free(fw_map); - plist_dict_set_item(response, "FirmwareData", plist_new_data(bin_plist, (uint64_t)bin_size)); + plist_dict_set_item(response, "FirmwareData", plist_new_data(bin_plist, bin_size)); free(bin_plist); return response; } -static plist_t restore_get_generic_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) +static plist_t restore_get_generic_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { plist_t request = NULL; plist_t response = NULL; @@ -2737,7 +3198,7 @@ static plist_t restore_get_generic_firmware_data(restored_client_t restore, stru return response; } -static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = "Baobab,TCON"; char *comp_path = NULL; @@ -2748,6 +3209,17 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct plist_t response = NULL; int ret; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Baobab request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2759,13 +3231,13 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); /* add Baobab,* tags from info dictionary to parameters */ plist_dict_merge(¶meters, p_info); /* add required tags for Baobab TSS request */ - tss_request_add_tcon_tags(request, parameters, NULL); + tss_request_add_tcon_tags(request, parameters, device_generated_request); plist_free(parameters); @@ -2784,7 +3256,7 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct error("ERROR: No 'Baobab,Ticket' in TSS response, this might not work\n"); } - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; } @@ -2798,7 +3270,7 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct return NULL; } - plist_dict_set_item(response, "FirmwareData", plist_new_data((char *)component_data, (uint64_t)component_size)); + plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, component_size)); free(component_data); component_data = NULL; component_size = 0; @@ -2806,7 +3278,7 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct return response; } -static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info) +static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char comp_name[64]; char *comp_path = NULL; @@ -2822,6 +3294,17 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct uint32_t tag = 0; int ret; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Timer request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2832,7 +3315,7 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct parameters = plist_new_dict(); /* add manifest for current build_identity to parameters */ - tss_parameters_add_from_manifest(parameters, build_identity, true); + tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true); plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1)); if (client->image4supported) { @@ -2851,7 +3334,7 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct } else { plist_t info_dict = plist_array_get_item(info_array, 0); plist_t hwid = plist_dict_get_item(info_dict, "HardwareID"); - tag = (uint32_t)_plist_dict_get_uint(info_dict, "TagNumber"); + tag = (uint32_t)plist_dict_get_uint(info_dict, "TagNumber"); char key[64]; plist_dict_set_item(parameters, "TagNumber", plist_new_uint(tag)); @@ -2862,25 +3345,25 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct } sprintf(key, "Timer,ChipID,%u", tag); - _plist_dict_copy_uint(parameters, hwid, key, "ChipID"); + plist_dict_copy_uint(parameters, hwid, key, "ChipID"); sprintf(key, "Timer,BoardID,%u", tag); - _plist_dict_copy_uint(parameters, hwid, key, "BoardID"); + plist_dict_copy_uint(parameters, hwid, key, "BoardID"); sprintf(key, "Timer,ECID,%u", tag); - _plist_dict_copy_uint(parameters, hwid, key, "ECID"); + plist_dict_copy_uint(parameters, hwid, key, "ECID"); sprintf(key, "Timer,Nonce,%u", tag); - _plist_dict_copy_data(parameters, hwid, key, "Nonce"); + plist_dict_copy_data(parameters, hwid, key, "Nonce"); sprintf(key, "Timer,SecurityMode,%u", tag); - _plist_dict_copy_bool(parameters, hwid, key, "SecurityMode"); + plist_dict_copy_bool(parameters, hwid, key, "SecurityMode"); sprintf(key, "Timer,SecurityDomain,%u", tag); - _plist_dict_copy_uint(parameters, hwid, key, "SecurityDomain"); + plist_dict_copy_uint(parameters, hwid, key, "SecurityDomain"); sprintf(key, "Timer,ProductionMode,%u", tag); - _plist_dict_copy_uint(parameters, hwid, key, "ProductionStatus"); + plist_dict_copy_uint(parameters, hwid, key, "ProductionStatus"); } plist_t ap_info = plist_dict_get_item(p_info, "APInfo"); if (!ap_info) { @@ -2892,7 +3375,7 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct } /* add required tags for Timer TSS request */ - tss_request_add_timer_tags(request, parameters, NULL); + tss_request_add_timer_tags(request, parameters, device_generated_request); plist_free(parameters); @@ -2911,8 +3394,8 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct } sprintf(comp_name, "Timer,RTKitOS,%u", tag); - if (build_identity_has_component(build_identity, comp_name)) { - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_has_component(client->restore->build_identity, comp_name)) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; } @@ -2939,8 +3422,8 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct } sprintf(comp_name, "Timer,RestoreRTKitOS,%u", tag); - if (build_identity_has_component(build_identity, comp_name)) { - if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) { + if (build_identity_has_component(client->restore->build_identity, comp_name)) { + if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) { ftab_free(ftab); error("ERROR: Unable to get path for '%s' component\n", comp_name); return NULL; @@ -2983,7 +3466,7 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct ftab_write(ftab, &component_data, &component_size); ftab_free(ftab); - plist_dict_set_item(response, "FirmwareData", plist_new_data((char *)component_data, (uint64_t)component_size)); + plist_dict_set_item(response, "FirmwareData", plist_new_data((char*)component_data, component_size)); free(component_data); component_data = NULL; component_size = 0; @@ -2991,12 +3474,17 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct return response; } -static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments) +static plist_t restore_get_cryptex1_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { plist_t parameters = NULL; plist_t request = NULL; plist_t response = NULL; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return NULL; + } + plist_t p_updater_name = plist_dict_get_item(arguments, "MessageArgUpdaterName"); const char* s_updater_name = plist_get_string_ptr(p_updater_name, NULL); @@ -3028,7 +3516,7 @@ static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, str for (i = 0; i < plist_array_get_size(build_identity_tags); i++) { plist_t node = plist_array_get_item(build_identity_tags, i); const char* key = plist_get_string_ptr(node, NULL); - plist_t item = plist_dict_get_item(build_identity, key); + plist_t item = plist_dict_get_item(client->restore->build_identity, key); if (item) { plist_dict_set_item(parameters, key, plist_copy(item)); } @@ -3043,10 +3531,10 @@ static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, str plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1)); } if (!plist_dict_get_item(parameters, "ApChipID")) { - _plist_dict_copy_uint(parameters, build_identity, "ApChipID", NULL); + plist_dict_copy_uint(parameters, client->restore->build_identity, "ApChipID", NULL); } if (!plist_dict_get_item(parameters, "ApBoardID")) { - _plist_dict_copy_uint(parameters, build_identity, "ApBoardID", NULL); + plist_dict_copy_uint(parameters, client->restore->build_identity, "ApBoardID", NULL); } /* add device generated request data to parameters */ @@ -3081,7 +3569,7 @@ static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, str return response; } -static int restore_send_firmware_updater_preflight(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) +static int restore_send_firmware_updater_preflight(struct idevicerestore_client_t* client, plist_t message) { plist_t dict = NULL; int restore_error; @@ -3091,11 +3579,18 @@ static int restore_send_firmware_updater_preflight(restored_client_t restore, st debug_plist(message); } + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + dict = plist_new_dict(); info("Sending FirmwareResponsePreflight now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Couldn't send FirmwareResponsePreflight data (%d)\n", restore_error); return -1; @@ -3105,7 +3600,7 @@ static int restore_send_firmware_updater_preflight(restored_client_t restore, st return 0; } -static int restore_send_firmware_updater_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message) +static int restore_send_firmware_updater_data(struct idevicerestore_client_t* client, plist_t message) { plist_t arguments; plist_t p_type, p_updater_name, p_loop_count, p_info; @@ -3116,6 +3611,11 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct char *s_updater_name = NULL; int restore_error; + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + if (idevicerestore_debug) { debug("DEBUG: %s: Got FirmwareUpdaterData request:\n", __func__); debug_plist(message); @@ -3162,7 +3662,7 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct plist_get_string_val(p_updater_name, &s_updater_name); if (strcmp(s_updater_name, "SE") == 0) { - fwdict = restore_get_se_firmware_data(restore, client, build_identity, p_info, arguments); + fwdict = restore_get_se_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get SE firmware data\n", __func__); goto error_out; @@ -3172,59 +3672,59 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct plist_t p_info2 = plist_dict_get_item(p_info, "YonkersDeviceInfo"); if (p_info2 && plist_get_node_type(p_info2) == PLIST_DICT) { fwtype = "Yonkers"; - fwdict = restore_get_yonkers_firmware_data(restore, client, build_identity, p_info2); + fwdict = restore_get_yonkers_firmware_data(client, p_info2, arguments); } else { - fwdict = restore_get_savage_firmware_data(restore, client, build_identity, p_info); + fwdict = restore_get_savage_firmware_data(client, p_info, arguments); } if (fwdict == NULL) { error("ERROR: %s: Couldn't get %s firmware data\n", __func__, fwtype); goto error_out; } } else if (strcmp(s_updater_name, "Rose") == 0) { - fwdict = restore_get_rose_firmware_data(restore, client, build_identity, p_info, arguments); + fwdict = restore_get_rose_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get Rose firmware data\n", __func__); goto error_out; } } else if (strcmp(s_updater_name, "T200") == 0) { - fwdict = restore_get_veridian_firmware_data(restore, client, build_identity, p_info); + fwdict = restore_get_veridian_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get Veridian firmware data\n", __func__); goto error_out; } } else if (strcmp(s_updater_name, "AppleTCON") == 0) { - fwdict = restore_get_tcon_firmware_data(restore, client, build_identity, p_info); + fwdict = restore_get_tcon_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get AppleTCON firmware data\n", __func__); goto error_out; } } else if (strcmp(s_updater_name, "PS190") == 0) { - fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments); + fwdict = restore_get_generic_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get PCON1 firmware data\n", __func__); goto error_out; } } else if (strcmp(s_updater_name, "AppleTypeCRetimer") == 0) { - fwdict = restore_get_timer_firmware_data(restore, client, build_identity, p_info); + fwdict = restore_get_timer_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get AppleTypeCRetimer firmware data\n", __func__); goto error_out; } } else if ((strcmp(s_updater_name, "Cryptex1") == 0) || (strcmp(s_updater_name, "Cryptex1LocalPolicy") == 0)) { - fwdict = restore_get_cryptex1_firmware_data(restore, client, build_identity, p_info, arguments); + fwdict = restore_get_cryptex1_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); goto error_out; } } else if (strcmp(s_updater_name, "Ace3") == 0) { - fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments); + fwdict = restore_get_generic_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); goto error_out; } } else { error("ERROR: %s: Got unknown updater name '%s', trying to discover from device generated request.\n", __func__, s_updater_name); - fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments); + fwdict = restore_get_generic_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name); goto error_out; @@ -3233,12 +3733,19 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct free(s_updater_name); s_updater_name = NULL; + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + dict = plist_new_dict(); plist_dict_set_item(dict, "FirmwareResponseData", fwdict); info("Sending FirmwareResponse data now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Couldn't send FirmwareResponse data (%d)\n", restore_error); goto error_out; @@ -3255,23 +3762,35 @@ error_out: return -1; } -static int restore_send_receipt_manifest(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity) +static int restore_send_receipt_manifest(struct idevicerestore_client_t* client, plist_t message) { plist_t dict; int restore_error; - plist_t manifest = plist_dict_get_item(build_identity, "Manifest"); + if (!client || !client->restore || !client->restore->build_identity) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + + plist_t manifest = plist_dict_get_item(client->restore->build_identity, "Manifest"); if (!manifest) { error("failed to get Manifest node from build_identity"); goto error_out; } + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + dict = plist_new_dict(); plist_dict_set_item(dict, "ReceiptManifest", plist_copy(manifest)); info("Sending ReceiptManifest data now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); plist_free(dict); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Couldn't send ReceiptManifest data (%d)\n", restore_error); goto error_out; @@ -3388,7 +3907,7 @@ static int restore_bootability_send_one(void *ctx, ipsw_archive_t ipsw, const ch return ret; } -static int restore_send_bootability_bundle_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message, idevice_t device) +static int restore_send_bootability_bundle_data(struct idevicerestore_client_t* client, plist_t message) { if (idevicerestore_debug) { debug("DEBUG: %s: Got BootabilityBundle request:\n", __func__); @@ -3404,9 +3923,14 @@ static int restore_send_bootability_bundle_data(restored_client_t restore, struc idevice_connection_t connection = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; + if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) { + error("ERROR: %s: idevicerestore client not initialized?!\n", __func__); + return -1; + } + debug("Connecting to BootabilityBundle data port\n"); while (--attempts > 0) { - device_error = idevice_connect(device, data_port, &connection); + device_error = idevice_connect(client->restore->device, data_port, &connection); if (device_error == IDEVICE_E_SUCCESS) { break; } @@ -3451,17 +3975,17 @@ plist_t restore_get_build_identity(struct idevicerestore_client_t* client, uint8 plist_t unique_id_node = plist_dict_get_item(client->build_manifest, "UniqueBuildID"); if (unique_id_node) { - printf("UniqueBuildID: "); + info("UniqueBuildID: "); plist_write_to_stream(unique_id_node, stdout, PLIST_FORMAT_PRINT, PLIST_OPT_NONE); } return build_identity; } -plist_t restore_get_build_identity_from_request(struct idevicerestore_client_t* client, plist_t msg) +plist_t restore_get_build_identity_from_request(struct idevicerestore_client_t* client, plist_t message) { - plist_t args = plist_dict_get_item(msg, "Arguments"); - return restore_get_build_identity(client, _plist_dict_get_bool(args, "IsRecoveryOS")); + plist_t args = plist_dict_get_item(message, "Arguments"); + return restore_get_build_identity(client, plist_dict_get_bool(args, "IsRecoveryOS")); } int extract_macos_variant(plist_t build_identity, char** output) @@ -3540,7 +4064,7 @@ int extract_global_manifest(struct idevicerestore_client_t* client, plist_t buil struct _restore_send_file_data_ctx { struct idevicerestore_client_t* client; - restored_client_t restore; + restore_service_client_t service; int last_progress; }; @@ -3554,13 +4078,22 @@ static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, voi // Send FileDataDone to mark end of transfer plist_dict_set_item(dict, "FileDataDone", plist_new_bool(1)); } - restored_error_t restore_error = restored_send(rctx->restore, dict); + restored_error_t restore_error = _restore_service_send(rctx->service, dict, 0); if (restore_error != RESTORE_E_SUCCESS) { plist_free(dict); error("ERROR: %s: Failed to send data (%d)\n", __func__, restore_error); return -1; } plist_free(dict); + + /* special handling for AEA image format */ + if (done == 0 && (memcmp(data, "AEA1", 4) == 0)) { + info("Encountered First Chunk in AEA image\n"); + plist_t message = NULL; + _restore_service_recv(rctx->service, &message); + restore_send_url_asset(rctx->client, message); + } + if (total_size > 0x1000000) { double progress = (double)done / (double)total_size; int progress_int = (int)(progress*100.0); @@ -3572,15 +4105,15 @@ static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, voi return 0; } -int restore_send_personalized_boot_object_v3(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg, plist_t build_identity) +int restore_send_personalized_boot_object_v3(struct idevicerestore_client_t* client, plist_t message) { if (idevicerestore_debug) { debug("DEBUG: %s: Got PersonalizedBootObjectV3 request:\n", __func__); - debug_plist(msg); + debug_plist(message); } char *image_name = NULL; - plist_t node = plist_access_path(msg, 2, "Arguments", "ImageName"); + plist_t node = plist_access_path(message, 2, "Arguments", "ImageName"); if (!node || plist_get_node_type(node) != PLIST_STRING) { debug("Failed to parse arguments from PersonalizedBootObjectV3 plist\n"); return -1; @@ -3602,7 +4135,7 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i info("About to send %s...\n", component); if (strcmp(image_name, "__GlobalManifest__") == 0) { - int ret = extract_global_manifest(client, build_identity, NULL, &data, &size); + int ret = extract_global_manifest(client, client->restore->build_identity, NULL, &data, &size); if (ret != 0) { return -1; } @@ -3626,7 +4159,7 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i } } if (!path) { - plist_t build_identity = restore_get_build_identity_from_request(client, msg); + plist_t build_identity = restore_get_build_identity_from_request(client, message); if (!build_identity) { error("ERROR: Unable to find a matching build identity\n"); return -1; @@ -3658,11 +4191,17 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i } } + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending %s now (%" PRIu64 " bytes)...\n", component, (uint64_t)size); struct _restore_send_file_data_ctx rctx; rctx.client = client; - rctx.restore = restore; + rctx.service = service; rctx.last_progress = 0; int64_t i = size; @@ -3670,6 +4209,7 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i int blob_size = i > 8192 ? 8192 : i; if (_restore_send_file_data(&rctx, (data + size - i), blob_size, size-i, size) < 0) { free(data); + _restore_service_free(service); error("ERROR: Unable to send component %s data\n", component); return -1; } @@ -3679,19 +4219,21 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i _restore_send_file_data(&rctx, NULL, 0, size-i, size); + _restore_service_free(service); + info("Done sending %s\n", component); return 0; } -int restore_send_source_boot_object_v4(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg, plist_t build_identity) +int restore_send_source_boot_object_v4(struct idevicerestore_client_t* client, plist_t message) { if (idevicerestore_debug) { debug("DEBUG: %s: Got SourceBootObjectV4 request:\n", __func__); - debug_plist(msg); + debug_plist(message); } char *image_name = NULL; - plist_t node = plist_access_path(msg, 2, "Arguments", "ImageName"); + plist_t node = plist_access_path(message, 2, "Arguments", "ImageName"); if (!node || plist_get_node_type(node) != PLIST_STRING) { debug("Failed to parse arguments from SourceBootObjectV4 plist\n"); return -1; @@ -3716,7 +4258,7 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice if (strcmp(image_name, "__GlobalManifest__") == 0) { char *variant = NULL; - plist_t node = plist_access_path(msg, 2, "Arguments", "Variant"); + plist_t node = plist_access_path(message, 2, "Arguments", "Variant"); if (!node || plist_get_node_type(node) != PLIST_STRING) { debug("Failed to parse arguments from SourceBootObjectV4 plist\n"); return -1; @@ -3727,7 +4269,7 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice return -1; } - path = extract_global_manifest_path(build_identity, variant); + path = extract_global_manifest_path(client->restore->build_identity, variant); } else if (strcmp(image_name, "__RestoreVersion__") == 0) { path = strdup("RestoreVersion.plist"); } else if (strcmp(image_name, "__SystemVersion__") == 0) { @@ -3740,7 +4282,7 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice } } if (!path) { - plist_t build_identity = restore_get_build_identity_from_request(client, msg); + plist_t build_identity = restore_get_build_identity_from_request(client, message); if (build_identity_get_component_path(build_identity, component, &path) < 0) { error("ERROR: Unable to find %s path from build identity\n", component); return -1; @@ -3756,25 +4298,34 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice uint64_t fsize = 0; ipsw_get_file_size(client->ipsw, path, &fsize); + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("Sending %s now (%" PRIu64 " bytes)\n", component, fsize); struct _restore_send_file_data_ctx rctx; rctx.client = client; - rctx.restore = restore; + rctx.service = service; rctx.last_progress = 0; if (ipsw_extract_send(client->ipsw, path, 8192, (ipsw_send_cb)_restore_send_file_data, &rctx) < 0) { free(path); + _restore_service_free(service); error("ERROR: Failed to send component %s\n", component); return -1; } free(path); + _restore_service_free(service); + info("Done sending %s\n", component); return 0; } -int restore_send_restore_local_policy(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg) +int restore_send_restore_local_policy(struct idevicerestore_client_t* client, plist_t message) { unsigned int size = 0; unsigned char* data = NULL; @@ -3791,7 +4342,7 @@ int restore_send_restore_local_policy(restored_client_t restore, struct idevicer // The Update mode does not have a specific build identity for the recovery os. plist_t build_identity = restore_get_build_identity(client, client->flags & FLAG_ERASE ? 1 : 0); - int ret = get_recovery_os_local_policy_tss_response(client, build_identity, &client->tss_localpolicy, plist_dict_get_item(msg, "Arguments")); + int ret = get_recovery_os_local_policy_tss_response(client, build_identity, &client->tss_localpolicy, plist_dict_get_item(message, "Arguments")); if (ret < 0) { error("ERROR: Unable to get recovery os local policy tss response\n"); return -1; @@ -3808,7 +4359,15 @@ int restore_send_restore_local_policy(restored_client_t restore, struct idevicer plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "Ap,LocalPolicy", plist_new_data((char*)data, size)); - int restore_error = restored_send(restore, dict); + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + + int restore_error = 0; + restore_error = _restore_service_send(service, dict, 0); + _restore_service_free(service); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to send component %s data\n", component); return -1; @@ -3820,19 +4379,25 @@ int restore_send_restore_local_policy(restored_client_t restore, struct idevicer return 0; } -int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg) +int restore_send_buildidentity(struct idevicerestore_client_t* client, plist_t message) { restored_error_t restore_error; plist_t dict; + restore_service_client_t service = _restore_get_service_client_for_data_request(client, message); + if (!service) { + error("ERROR: %s: Unable to connect to service client\n", __func__); + return -1; + } + info("About to send BuildIdentity Dict...\n"); - plist_t build_identity = restore_get_build_identity_from_request(client, msg); + plist_t build_identity = restore_get_build_identity_from_request(client, message); dict = plist_new_dict(); plist_dict_set_item(dict, "BuildIdentityDict", plist_copy(build_identity)); - plist_t node = plist_access_path(msg, 2, "Arguments", "Variant"); + plist_t node = plist_access_path(message, 2, "Arguments", "Variant"); if(node) { plist_dict_set_item(dict, "Variant", plist_copy(node)); } else { @@ -3840,7 +4405,8 @@ int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_ } info("Sending BuildIdentityDict now...\n"); - restore_error = restored_send(restore, dict); + restore_error = _restore_service_send(service, dict, 0); + _restore_service_free(service); plist_free(dict); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to send BuildIdentityDict (%d)\n", restore_error); @@ -3851,7 +4417,7 @@ int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_ return 0; } -int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity) +int restore_handle_data_request_msg(struct idevicerestore_client_t* client, plist_t message) { plist_t node = NULL; @@ -3860,38 +4426,38 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev node = plist_dict_get_item(message, "DataType"); if (node && PLIST_STRING == plist_get_node_type(node)) { const char *type = plist_get_string_ptr(node, NULL); - +debug("%s: type = %s\n", __func__, type); // this request is sent when restored is ready to receive the filesystem if (!strcmp(type, "SystemImageData")) { - if(restore_send_filesystem(client, device, build_identity) < 0) { + if (restore_send_filesystem(client, message) < 0) { error("ERROR: Unable to send filesystem\n"); return -2; } } else if (!strcmp(type, "BuildIdentityDict")) { - if (restore_send_buildidentity(restore, client, message) < 0) { + if (restore_send_buildidentity(client, message) < 0) { error("ERROR: Unable to send RootTicket\n"); return -1; } } else if (!strcmp(type, "PersonalizedBootObjectV3")) { - if (restore_send_personalized_boot_object_v3(restore, client, message, build_identity) < 0) { + if (restore_send_personalized_boot_object_v3(client, message) < 0) { error("ERROR: Unable to send PersonalizedBootObjectV3\n"); return -1; } } else if (!strcmp(type, "SourceBootObjectV4")) { - if (restore_send_source_boot_object_v4(restore, client, message, build_identity) < 0) { + if (restore_send_source_boot_object_v4(client, message) < 0) { error("ERROR: Unable to send SourceBootObjectV4\n"); return -1; } } else if (!strcmp(type, "RecoveryOSLocalPolicy")) { - if (restore_send_restore_local_policy(restore, client, message) < 0) { + if (restore_send_restore_local_policy(client, message) < 0) { error("ERROR: Unable to send RecoveryOSLocalPolicy\n"); return -1; } @@ -3899,7 +4465,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev // this request is sent when restored is ready to receive the filesystem else if (!strcmp(type, "RecoveryOSASRImage")) { - if(restore_send_filesystem(client, device, build_identity) < 0) { + if (restore_send_filesystem(client, message) < 0) { error("ERROR: Unable to send filesystem\n"); return -2; } @@ -3907,7 +4473,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev // Send RecoveryOS RTD else if(!strcmp(type, "RecoveryOSRootTicketData")) { - if (restore_send_recovery_os_root_ticket(restore, client) < 0) { + if (restore_send_recovery_os_root_ticket(client, message) < 0) { error("ERROR: Unable to send RootTicket\n"); return -1; } @@ -3915,35 +4481,35 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev // send RootTicket (== APTicket from the TSS request) else if (!strcmp(type, "RootTicket")) { - if (restore_send_root_ticket(restore, client) < 0) { + if (restore_send_root_ticket(client, message) < 0) { error("ERROR: Unable to send RootTicket\n"); return -1; } } // send KernelCache else if (!strcmp(type, "KernelCache")) { - if (restore_send_component(restore, client, build_identity, "KernelCache", NULL) < 0) { + if (restore_send_component(client, message, "KernelCache", NULL) < 0) { error("ERROR: Unable to send kernelcache\n"); return -1; } } else if (!strcmp(type, "DeviceTree")) { - if (restore_send_component(restore, client, build_identity, "DeviceTree", NULL) < 0) { + if (restore_send_component(client, message, "DeviceTree", NULL) < 0) { error("ERROR: Unable to send DeviceTree\n"); return -1; } } else if (!strcmp(type, "SystemImageRootHash")) { - if (restore_send_component(restore, client, build_identity, "SystemVolume", type) < 0) { + if (restore_send_component(client, message, "SystemVolume", type) < 0) { error("ERROR: Unable to send SystemImageRootHash data\n"); return -1; } } else if (!strcmp(type, "SystemImageCanonicalMetadata")) { - if (restore_send_component(restore, client, build_identity, "Ap,SystemVolumeCanonicalMetadata", type) < 0) { + if (restore_send_component(client, message, "Ap,SystemVolumeCanonicalMetadata", type) < 0) { error("ERROR: Unable to send SystemImageCanonicalMetadata data\n"); return -1; } @@ -3951,7 +4517,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev else if (!strcmp(type, "NORData")) { if((client->flags & FLAG_EXCLUDE) == 0) { - if(restore_send_nor(restore, client, build_identity, message) < 0) { + if(restore_send_nor(client, message) < 0) { error("ERROR: Unable to send NOR data\n"); return -1; } @@ -3962,75 +4528,89 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev } else if (!strcmp(type, "BasebandData")) { - if(restore_send_baseband_data(restore, client, build_identity, message) < 0) { + if(restore_send_baseband_data(client, message) < 0) { error("ERROR: Unable to send baseband data\n"); return -1; } } else if (!strcmp(type, "FDRTrustData")) { - if(restore_send_fdr_trust_data(restore, device) < 0) { + if(restore_send_fdr_trust_data(client, message) < 0) { error("ERROR: Unable to send FDR Trust data\n"); return -1; } } else if (!strcmp(type, "FUDData")) { - if(restore_send_image_data(restore, client, build_identity, message, "FUDImageList", "IsFUDFirmware", "FUDImageData") < 0) { + if(restore_send_image_data(client, message, "FUDImageList", "IsFUDFirmware", "FUDImageData") < 0) { error("ERROR: Unable to send FUD data\n"); return -1; } } else if (!strcmp(type, "FirmwareUpdaterPreflight")) { - if(restore_send_firmware_updater_preflight(restore, client, build_identity, message) < 0) { + if(restore_send_firmware_updater_preflight(client, message) < 0) { error("ERROR: Unable to send FirmwareUpdaterPreflight\n"); return -1; } } else if (!strcmp(type, "FirmwareUpdaterData")) { - if(restore_send_firmware_updater_data(restore, client, build_identity, message) < 0) { + if(restore_send_firmware_updater_data(client, message) < 0) { error("ERROR: Unable to send FirmwareUpdater data\n"); return -1; } } else if (!strcmp(type, "PersonalizedData")) { - if(restore_send_image_data(restore, client, build_identity, message, "ImageList", NULL, "ImageData") < 0) { + if(restore_send_image_data(client, message, "ImageList", NULL, "ImageData") < 0) { error("ERROR: Unable to send Personalized data\n"); return -1; } } else if (!strcmp(type, "EANData")) { - if(restore_send_image_data(restore, client, build_identity, message, "EANImageList", "IsEarlyAccessFirmware", "EANData") < 0) { + if(restore_send_image_data(client, message, "EANImageList", "IsEarlyAccessFirmware", "EANData") < 0) { error("ERROR: Unable to send Personalized data\n"); return -1; } } else if (!strcmp(type, "BootabilityBundle")) { - if (restore_send_bootability_bundle_data(restore, client, build_identity, message, device) < 0) { + if (restore_send_bootability_bundle_data(client, message) < 0) { error("ERROR: Unable to send BootabilityBundle data\n"); return -1; } } else if (!strcmp(type, "ReceiptManifest")) { - if (restore_send_receipt_manifest(restore, client, build_identity) < 0) { + if (restore_send_receipt_manifest(client, message) < 0) { error("ERROR: Unable to send ReceiptManifest data\n"); return -1; } } else if (!strcmp(type, "BasebandUpdaterOutputData")) { - if (restore_handle_baseband_updater_output_data(restore, client, device, message) < 0) { + if (restore_handle_baseband_updater_output_data(client, message) < 0) { error("ERROR: Unable to send BasebandUpdaterOutputData data\n"); return -1; } } + else if (!strcmp(type, "URLAsset")) { + if (restore_send_url_asset(client, message) < 0) { + error("ERROR: Unable to send URLAsset data\n"); + return -1; + } + } + + else if (!strcmp(type, "StreamedImageDecryptionKey")) { + if (restore_send_streamed_image_decryption_key(client, message) < 0) { + error("ERROR: Unable to send StreamedImageDecryptionKey data\n"); + return -1; + } + } + else { // Unknown DataType!! error("Unknown data request '%s' received\n", type); @@ -4041,6 +4621,70 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev return 0; } +struct _restore_async_args { + struct idevicerestore_client_t* client; + plist_t message; +}; + +static void* _restore_handle_async_data_request(void* args) +{ + struct _restore_async_args* async_args = (struct _restore_async_args*)args; + struct idevicerestore_client_t* client = async_args->client; + plist_t message = async_args->message; + free(async_args); + + int err = restore_handle_data_request_msg(client, message); + if (err < 0) { + client->async_err = err; + client->flags |= FLAG_QUIT; + } + + plist_free(message); + return NULL; +} + +static int restore_handle_restored_crash(struct idevicerestore_client_t* client, plist_t message) +{ + plist_t backtrace = plist_dict_get_item(message, "RestoredBacktrace"); + info("*** restored crashed, backtrace following ***"); + if (PLIST_IS_STRING(backtrace)) { + info("%s\n", plist_get_string_ptr(backtrace, NULL)); + } else if (PLIST_IS_ARRAY(backtrace)) { + uint32_t i = 0; + for (i = 0; i < plist_array_get_size(backtrace); i++) { + plist_t line = plist_array_get_item(backtrace, i); + info("\t%s\n", plist_get_string_ptr(line, NULL)); + } + } else { + debug_plist(message); + } + return 0; +} + +static int restore_handle_async_wait(struct idevicerestore_client_t* client, plist_t message) +{ + debug("AsyncWait\n"); + if (idevicerestore_debug) + debug_plist(message); + return 0; +} + +static int restore_handle_restore_attestation(struct idevicerestore_client_t* client, plist_t message) +{ + if (idevicerestore_debug) + debug_plist(message); + debug("Sending RestoreShouldAttest: false\n"); + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "RestoreShouldAttest", plist_new_bool(0)); + restored_error_t restore_error = restored_send(client->restore->client, dict); + plist_free(dict); + if (restore_error != RESTORE_E_SUCCESS) { + error("ERROR: Unable to send RestoreShouldAttest (%d)\n", restore_error); + return -1; + } + return 0; +} + // Extracted from ac2 plist_t restore_supported_data_types() { @@ -4107,6 +4751,10 @@ plist_t restore_supported_data_types() plist_dict_set_item(dict, "RestoreLocalPolicy", plist_new_bool(1)); plist_dict_set_item(dict, "AuthInstallCACert", plist_new_bool(1)); plist_dict_set_item(dict, "OverlayRootDataForKeyIndex", plist_new_bool(1)); + plist_dict_set_item(dict, "FirmwareUpdaterDataV3", plist_new_bool(1)); + plist_dict_set_item(dict, "MessageUseStreamedImageFile", plist_new_bool(1)); + plist_dict_set_item(dict, "UpdateVolumeOverlayRootDataCount", plist_new_bool(1)); + plist_dict_set_item(dict, "URLAsset", plist_new_bool(1)); return dict; } @@ -4127,6 +4775,9 @@ plist_t restore_supported_message_types() plist_dict_set_item(dict, "ReceivedFinalStatusMsg", plist_new_bool(0)); plist_dict_set_item(dict, "RestoredCrash", plist_new_bool(1)); plist_dict_set_item(dict, "StatusMsg", plist_new_bool(0)); + plist_dict_set_item(dict, "AsyncDataRequestMsg", plist_new_bool(1)); + plist_dict_set_item(dict, "AsyncWait", plist_new_bool(1)); + plist_dict_set_item(dict, "RestoreAttestation", plist_new_bool(1)); return dict; } @@ -4166,6 +4817,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit } info("Device %s has successfully entered restore mode\n", client->udid); + client->restore->build_identity = build_identity; restore = client->restore->client; device = client->restore->device; @@ -4289,7 +4941,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit plist_dict_set_item(opts, "BBUpdaterState", bbus); - _plist_dict_copy_data(opts, client->preflight_info, "BasebandNonce", "Nonce"); + plist_dict_copy_data(opts, client->preflight_info, "BasebandNonce", "Nonce"); } plist_dict_set_item(opts, "SupportedDataTypes", restore_supported_data_types()); @@ -4363,6 +5015,18 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit // FIXME: does this have any effect actually? plist_dict_set_item(opts, "UpdateBaseband", plist_new_bool(0)); + // Added for iOS 18.0 beta 1 + plist_dict_set_item(opts, "HostHasFixFor99053849", plist_new_bool(1)); + plist_dict_set_item(opts, "SystemImageFormat", plist_new_string("AEAWrappedDiskImage")); + plist_dict_set_item(opts, "WaitForDeviceConnectionToFinishStateMachine", plist_new_bool(0)); + plist_t async_data_types = plist_new_dict(); + plist_dict_set_item(async_data_types, "BasebandData", plist_new_bool(0)); + plist_dict_set_item(async_data_types, "RecoveryOSASRImage", plist_new_bool(0)); + plist_dict_set_item(async_data_types, "StreamedImageDecryptionKey", plist_new_bool(0)); + plist_dict_set_item(async_data_types, "SystemImageData", plist_new_bool(0)); + plist_dict_set_item(async_data_types, "URLAsset", plist_new_bool(1)); + plist_dict_set_item(opts, "SupportedAsyncDataTypes", async_data_types); + plist_t sep = plist_access_path(build_identity, 3, "Manifest", "SEP", "Info"); if (sep) { node = plist_dict_get_item(sep, "RequiredCapacity"); @@ -4465,7 +5129,22 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit // files sent to the server by the client. these data requests include // SystemImageData, RootTicket, KernelCache, NORData and BasebandData requests if (!strcmp(type, "DataRequestMsg")) { - err = restore_handle_data_request_msg(client, device, restore, message, build_identity); + err = restore_handle_data_request_msg(client, message); + } + + // async data request message + else if (!strcmp(type, "AsyncDataRequestMsg")) { + THREAD_T t = THREAD_T_NULL; + struct _restore_async_args* args = (struct _restore_async_args*)malloc(sizeof(struct _restore_async_args)); + args->client = client; + args->message = plist_copy(message); + if (thread_new(&t, _restore_handle_async_data_request, args) < 0) { + free(args); + error("ERROR: Failed to start async data request handler thread!\n"); + err = -1; + } else { + thread_detach(t); + } } // restore logs are available if a previous restore failed @@ -4482,7 +5161,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit // status messages usually indicate the current state of the restored // process or often to signal an error has been encountered else if (!strcmp(type, "StatusMsg")) { - err = restore_handle_status_msg(restore, message); + err = restore_handle_status_msg(client, message); if (restore_finished) { plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "MsgType", plist_new_string("ReceivedFinalStatusMsg")); @@ -4501,7 +5180,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit node = plist_dict_get_item(message, "CHECKPOINT_ID"); if (!node || plist_get_node_type(node) != PLIST_INT) { debug("Failed to parse checkpoint id from checkpoint plist\n"); - return -1; + err = -1; + break; } plist_get_uint_val(node, &ckpt_id); // Get checkpoint_name @@ -4511,7 +5191,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit node = plist_dict_get_item(message, "CHECKPOINT_RESULT"); if (!node || plist_get_node_type(node) != PLIST_INT) { debug("Failed to parse checkpoint result from checkpoint plist\n"); - return -1; + err = -1; + break; } plist_get_int_val(node, &ckpt_res); // Get checkpoint complete @@ -4537,12 +5218,26 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit // baseband update message else if (!strcmp(type, "BBUpdateStatusMsg")) { - err = restore_handle_bb_update_status_msg(restore, message); + err = restore_handle_bb_update_status_msg(client, message); } // baseband updater output data request else if (!strcmp(type, "BasebandUpdaterOutputData")) { - err = restore_handle_baseband_updater_output_data(restore, client, device, message); + err = restore_handle_baseband_updater_output_data(client, message); + } + + // handle restored crash, print backtrace + else if (!strcmp(type, "RestoredCrash")) { + err = restore_handle_restored_crash(client, message); + } + + // handle async wait + else if (!strcmp(type, "AsyncWait")) { + err = restore_handle_async_wait(client, message); + } + + else if (!strcmp(type, "RestoreAttestation")) { + err = restore_handle_restore_attestation(client, message); } // there might be some other message types i'm not aware of, but I think @@ -4557,6 +5252,9 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit plist_free(message); message = NULL; } + if (client->async_err != 0) { + err = client->async_err; + } #ifdef HAVE_REVERSE_PROXY reverse_proxy_client_free(rproxy); diff --git a/src/restore.h b/src/restore.h index 765f374..763331d 100644 --- a/src/restore.h +++ b/src/restore.h @@ -40,6 +40,7 @@ struct restore_client_t { unsigned int operation; uint64_t protocol_version; restored_client_t client; + plist_t build_identity; }; int restore_check_mode(struct idevicerestore_client_t* client); @@ -49,16 +50,16 @@ void restore_client_free(struct idevicerestore_client_t* client); int restore_is_image4_supported(struct idevicerestore_client_t* client); int restore_reboot(struct idevicerestore_client_t* client); const char* restore_progress_string(unsigned int operation); -int restore_handle_status_msg(restored_client_t client, plist_t msg); -int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t msg); -int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity); -int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message); -int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client); -int restore_send_component(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* component_name); +int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t message); +int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t message); +int restore_handle_data_request_msg(struct idevicerestore_client_t* client, plist_t message); +int restore_send_nor(struct idevicerestore_client_t* client, plist_t message); +int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t message); +int restore_send_component(struct idevicerestore_client_t* client, plist_t message, const char* component, const char* component_name); int restore_device(struct idevicerestore_client_t* client, plist_t build_identity); int restore_open_with_timeout(struct idevicerestore_client_t* client); -int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, plist_t build_identity); -int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device); +int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t message); +int restore_send_fdr_trust_data(struct idevicerestore_client_t* client, plist_t message); #ifdef __cplusplus } diff --git a/src/sha1.c b/src/sha1.c deleted file mode 100644 index 02557ff..0000000 --- a/src/sha1.c +++ /dev/null @@ -1,294 +0,0 @@ -/* -SHA-1 in C -By Steve Reid <steve@edmweb.com> -100% Public Domain -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#define SHA1HANDSOFF - -#include <stdio.h> -#include <string.h> - -/* for uint32_t */ -#include <stdint.h> - -#include "sha1.h" - - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#if BYTE_ORDER == LITTLE_ENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#elif BYTE_ORDER == BIG_ENDIAN -#define blk0(i) block->l[i] -#else -#error "Endianness not defined!" -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void SHA1Transform( - uint32_t state[5], - const unsigned char buffer[64] -) -{ - uint32_t a, b, c, d, e; - - typedef union - { - unsigned char c[64]; - uint32_t l[16]; - } CHAR64LONG16; - -#ifdef SHA1HANDSOFF - CHAR64LONG16 block[1]; /* use array to appear as a pointer */ - - memcpy(block, buffer, 64); -#else - /* The following had better never be used because it causes the - * pointer-to-const buffer to be cast into a pointer to non-const. - * And the result is written through. I threw a "const" in, hoping - * this will cause a diagnostic. - */ - CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a, b, c, d, e, 0); - R0(e, a, b, c, d, 1); - R0(d, e, a, b, c, 2); - R0(c, d, e, a, b, 3); - R0(b, c, d, e, a, 4); - R0(a, b, c, d, e, 5); - R0(e, a, b, c, d, 6); - R0(d, e, a, b, c, 7); - R0(c, d, e, a, b, 8); - R0(b, c, d, e, a, 9); - R0(a, b, c, d, e, 10); - R0(e, a, b, c, d, 11); - R0(d, e, a, b, c, 12); - R0(c, d, e, a, b, 13); - R0(b, c, d, e, a, 14); - R0(a, b, c, d, e, 15); - R1(e, a, b, c, d, 16); - R1(d, e, a, b, c, 17); - R1(c, d, e, a, b, 18); - R1(b, c, d, e, a, 19); - R2(a, b, c, d, e, 20); - R2(e, a, b, c, d, 21); - R2(d, e, a, b, c, 22); - R2(c, d, e, a, b, 23); - R2(b, c, d, e, a, 24); - R2(a, b, c, d, e, 25); - R2(e, a, b, c, d, 26); - R2(d, e, a, b, c, 27); - R2(c, d, e, a, b, 28); - R2(b, c, d, e, a, 29); - R2(a, b, c, d, e, 30); - R2(e, a, b, c, d, 31); - R2(d, e, a, b, c, 32); - R2(c, d, e, a, b, 33); - R2(b, c, d, e, a, 34); - R2(a, b, c, d, e, 35); - R2(e, a, b, c, d, 36); - R2(d, e, a, b, c, 37); - R2(c, d, e, a, b, 38); - R2(b, c, d, e, a, 39); - R3(a, b, c, d, e, 40); - R3(e, a, b, c, d, 41); - R3(d, e, a, b, c, 42); - R3(c, d, e, a, b, 43); - R3(b, c, d, e, a, 44); - R3(a, b, c, d, e, 45); - R3(e, a, b, c, d, 46); - R3(d, e, a, b, c, 47); - R3(c, d, e, a, b, 48); - R3(b, c, d, e, a, 49); - R3(a, b, c, d, e, 50); - R3(e, a, b, c, d, 51); - R3(d, e, a, b, c, 52); - R3(c, d, e, a, b, 53); - R3(b, c, d, e, a, 54); - R3(a, b, c, d, e, 55); - R3(e, a, b, c, d, 56); - R3(d, e, a, b, c, 57); - R3(c, d, e, a, b, 58); - R3(b, c, d, e, a, 59); - R4(a, b, c, d, e, 60); - R4(e, a, b, c, d, 61); - R4(d, e, a, b, c, 62); - R4(c, d, e, a, b, 63); - R4(b, c, d, e, a, 64); - R4(a, b, c, d, e, 65); - R4(e, a, b, c, d, 66); - R4(d, e, a, b, c, 67); - R4(c, d, e, a, b, 68); - R4(b, c, d, e, a, 69); - R4(a, b, c, d, e, 70); - R4(e, a, b, c, d, 71); - R4(d, e, a, b, c, 72); - R4(c, d, e, a, b, 73); - R4(b, c, d, e, a, 74); - R4(a, b, c, d, e, 75); - R4(e, a, b, c, d, 76); - R4(d, e, a, b, c, 77); - R4(c, d, e, a, b, 78); - R4(b, c, d, e, a, 79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -#ifdef SHA1HANDSOFF - memset(block, '\0', sizeof(block)); -#endif -} - - -/* SHA1Init - Initialize new context */ - -void SHA1Init( - SHA1_CTX * context -) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1Update( - SHA1_CTX * context, - const unsigned char *data, - size_t len -) -{ - size_t i; - - size_t j; - - j = context->count[0]; - if ((context->count[0] += len << 3) < j) - context->count[1]++; - context->count[1] += (len >> 29); - j = (j >> 3) & 63; - if ((j + len) > 63) - { - memcpy(&context->buffer[j], data, (i = 64 - j)); - SHA1Transform(context->state, context->buffer); - for (; i + 63 < len; i += 64) - { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else - i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -void SHA1Final( - unsigned char digest[20], - SHA1_CTX * context -) -{ - unsigned i; - - unsigned char finalcount[8]; - - unsigned char c; - -#if 0 /* untested "improvement" by DHR */ - /* Convert context->count to a sequence of bytes - * in finalcount. Second element first, but - * big-endian order within element. - * But we do it all backwards. - */ - unsigned char *fcp = &finalcount[8]; - - for (i = 0; i < 2; i++) - { - uint32_t t = context->count[i]; - - int j; - - for (j = 0; j < 4; t >>= 8, j++) - *--fcp = (unsigned char) t} -#else - for (i = 0; i < 8; i++) - { - finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ - } -#endif - c = 0200; - SHA1Update(context, &c, 1); - while ((context->count[0] & 504) != 448) - { - c = 0000; - SHA1Update(context, &c, 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) - { - digest[i] = (unsigned char) - ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); - } - /* Wipe variables */ - memset(context, '\0', sizeof(*context)); - memset(&finalcount, '\0', sizeof(finalcount)); -} - -void SHA1( - const unsigned char *str, - size_t len, - unsigned char *hash_out -) -{ - SHA1_CTX ctx; - size_t ii; - - SHA1Init(&ctx); - for (ii=0; ii<len; ii+=1) - SHA1Update(&ctx, str + ii, 1); - SHA1Final(hash_out, &ctx); -} diff --git a/src/sha1.h b/src/sha1.h deleted file mode 100644 index c8e9f68..0000000 --- a/src/sha1.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA1_H -#define SHA1_H - -/* - SHA-1 in C - By Steve Reid <steve@edmweb.com> - 100% Public Domain - */ - -#include "stdint.h" - -typedef struct -{ - uint32_t state[5]; - uint32_t count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -void SHA1Transform( - uint32_t state[5], - const unsigned char buffer[64] - ); - -void SHA1Init( - SHA1_CTX * context - ); - -void SHA1Update( - SHA1_CTX * context, - const unsigned char *data, - size_t len - ); - -void SHA1Final( - unsigned char digest[20], - SHA1_CTX * context - ); - -void SHA1( - const unsigned char *str, - size_t len, - unsigned char *hash_out); - -#endif /* SHA1_H */ diff --git a/src/sha512.c b/src/sha512.c deleted file mode 100644 index 8f7c59d..0000000 --- a/src/sha512.c +++ /dev/null @@ -1,314 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org - */ - -#include "fixedint.h" -#include "sha512.h" - -/* the K array */ -static const uint64_t K[80] = { - UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), - UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), - UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), - UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), - UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), - UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), - UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), - UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), - UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), - UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), - UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), - UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), - UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), - UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), - UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), - UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), - UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), - UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), - UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), - UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), - UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), - UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), - UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), - UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), - UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), - UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), - UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), - UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), - UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), - UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), - UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), - UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), - UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), - UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), - UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), - UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), - UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), - UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), - UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), - UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) -}; - -/* Various logical functions */ - -#define ROR64c(x, y) \ - ( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \ - ((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF)) - -#define STORE64H(x, y) \ - { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ - (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ - (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ - (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } - -#define LOAD64H(x, y) \ - { x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \ - (((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \ - (((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \ - (((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } - - -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) ROR64c(x, n) -#define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n)) -#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) -#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) -#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) -#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) -#ifndef MIN - #define MIN(x, y) ( ((x)<(y))?(x):(y) ) -#endif - -/* compress 1024-bits */ -static int sha512_compress(sha512_context *md, unsigned char *buf) -{ - uint64_t S[8], W[80], t0, t1; - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->state[i]; - } - - /* copy the state into 1024-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD64H(W[i], buf + (8*i)); - } - - /* fill W[16..79] */ - for (i = 16; i < 80; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - -/* Compress */ - #define RND(a,b,c,d,e,f,g,h,i) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c);\ - d += t0; \ - h = t0 + t1; - - for (i = 0; i < 80; i += 8) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); - } - - #undef RND - - - - /* feedback */ - for (i = 0; i < 8; i++) { - md->state[i] = md->state[i] + S[i]; - } - - return 0; -} - - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return 0 if successful -*/ -int sha512_init(sha512_context * md) { - if (md == NULL) return 1; - - md->curlen = 0; - md->length = 0; - md->state[0] = UINT64_C(0x6a09e667f3bcc908); - md->state[1] = UINT64_C(0xbb67ae8584caa73b); - md->state[2] = UINT64_C(0x3c6ef372fe94f82b); - md->state[3] = UINT64_C(0xa54ff53a5f1d36f1); - md->state[4] = UINT64_C(0x510e527fade682d1); - md->state[5] = UINT64_C(0x9b05688c2b3e6c1f); - md->state[6] = UINT64_C(0x1f83d9abfb41bd6b); - md->state[7] = UINT64_C(0x5be0cd19137e2179); - md->num_qwords = 8; - - return 0; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return 0 if successful -*/ -int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen) -{ - size_t n; - size_t i; - int err; - if (md == NULL) return 1; - if (in == NULL) return 1; - if (md->curlen > sizeof(md->buf)) { - return 1; - } - while (inlen > 0) { - if (md->curlen == 0 && inlen >= 128) { - if ((err = sha512_compress (md, (unsigned char *)in)) != 0) { - return err; - } - md->length += 128 * 8; - in += 128; - inlen -= 128; - } else { - n = MIN(inlen, (128 - md->curlen)); - - for (i = 0; i < n; i++) { - md->buf[i + md->curlen] = in[i]; - } - - - md->curlen += n; - in += n; - inlen -= n; - if (md->curlen == 128) { - if ((err = sha512_compress (md, md->buf)) != 0) { - return err; - } - md->length += 8*128; - md->curlen = 0; - } - } - } - return 0; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (64 bytes) - @return 0 if successful -*/ -int sha512_final(sha512_context * md, unsigned char *out) -{ - int i; - - if (md == NULL) return 1; - if (out == NULL) return 1; - - if (md->curlen >= sizeof(md->buf)) { - return 1; - } - - /* increase the length of the message */ - md->length += md->curlen * UINT64_C(8); - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 112 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 112) { - while (md->curlen < 128) { - md->buf[md->curlen++] = (unsigned char)0; - } - sha512_compress(md, md->buf); - md->curlen = 0; - } - - /* pad upto 120 bytes of zeroes - * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash - * > 2^64 bits of data... :-) - */ - while (md->curlen < 120) { - md->buf[md->curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->length, md->buf+120); - sha512_compress(md, md->buf); - - /* copy output */ - for (i = 0; i < md->num_qwords; i++) { - STORE64H(md->state[i], out+(8*i)); - } - - return 0; -} - -int sha512(const unsigned char *message, size_t message_len, unsigned char *out) -{ - sha512_context ctx; - int ret; - if ((ret = sha512_init(&ctx))) return ret; - if ((ret = sha512_update(&ctx, message, message_len))) return ret; - if ((ret = sha512_final(&ctx, out))) return ret; - return 0; -} - -int sha384_init(sha384_context * md) { - if (md == NULL) return 1; - - md->curlen = 0; - md->length = 0; - md->state[0] = UINT64_C(0xcbbb9d5dc1059ed8); - md->state[1] = UINT64_C(0x629a292a367cd507); - md->state[2] = UINT64_C(0x9159015a3070dd17); - md->state[3] = UINT64_C(0x152fecd8f70e5939); - md->state[4] = UINT64_C(0x67332667ffc00b31); - md->state[5] = UINT64_C(0x8eb44a8768581511); - md->state[6] = UINT64_C(0xdb0c2e0d64f98fa7); - md->state[7] = UINT64_C(0x47b5481dbefa4fa4); - md->num_qwords = 6; - - return 0; -} - -int sha384_final(sha384_context * md, unsigned char* out) -{ - return sha512_final(md, out); -} - -int sha384_update(sha384_context * md, const unsigned char *in, size_t inlen) -{ - return sha512_update(md, in, inlen); -} - -int sha384(const unsigned char *message, size_t message_len, unsigned char *out) -{ - sha384_context ctx; - int ret; - if ((ret = sha384_init(&ctx))) return ret; - if ((ret = sha384_update(&ctx, message, message_len))) return ret; - if ((ret = sha384_final(&ctx, out))) return ret; - return 0; -} diff --git a/src/sha512.h b/src/sha512.h deleted file mode 100644 index 72db47b..0000000 --- a/src/sha512.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SHA512_H -#define SHA512_H - -#include <stddef.h> - -#include "fixedint.h" - -/* state */ -typedef struct sha512_context_ { - uint64_t length, state[8]; - size_t curlen; - unsigned char buf[128]; - int num_qwords; -} sha512_context; - -#define SHA512_DIGEST_LENGTH 64 - -int sha512_init(sha512_context * md); -int sha512_final(sha512_context * md, unsigned char *out); -int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen); -int sha512(const unsigned char *message, size_t message_len, unsigned char *out); - -typedef sha512_context sha384_context; - -#define SHA384_DIGEST_LENGTH 48 - -int sha384_init(sha384_context * md); -int sha384_final(sha384_context * md, unsigned char *out); -int sha384_update(sha384_context * md, const unsigned char *in, size_t inlen); -int sha384(const unsigned char *message, size_t message_len, unsigned char *out); - -#endif diff --git a/src/tss.c b/src/tss.c deleted file mode 100644 index 80591e7..0000000 --- a/src/tss.c +++ /dev/null @@ -1,1796 +0,0 @@ -/* - * tss.c - * Functions for communicating with Apple's TSS server - * - * Copyright (c) 2010-2013 Martin Szulecki. All Rights Reserved. - * Copyright (c) 2012 Nikias Bassen. All Rights Reserved. - * Copyright (c) 2010 Joshua Hill. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <curl/curl.h> -#include <plist/plist.h> - -#include "tss.h" -#include "img3.h" -#include "common.h" -#include "idevicerestore.h" - -#include "endianness.h" - -#define AUTH_VERSION "973.40.2" - -#ifdef WIN32 -#define TSS_CLIENT_VERSION_STRING "libauthinstall_Win-"AUTH_VERSION"" -#else -#define TSS_CLIENT_VERSION_STRING "libauthinstall-"AUTH_VERSION"" -#endif -#define ECID_STRSIZE 0x20 - -typedef struct { - int length; - char* content; -} tss_response; - -char* ecid_to_string(uint64_t ecid) -{ - char* ecid_string = malloc(ECID_STRSIZE); - memset(ecid_string, '\0', ECID_STRSIZE); - if (ecid == 0) { - error("ERROR: Invalid ECID passed.\n"); - return NULL; - } - snprintf(ecid_string, ECID_STRSIZE, "%"PRIu64, ecid); - return ecid_string; -} - -plist_t tss_request_new(plist_t overrides) -{ - plist_t request = plist_new_dict(); - - plist_dict_set_item(request, "@HostPlatformInfo", -#ifdef WIN32 - plist_new_string("windows") -#else - plist_new_string("mac") -#endif - ); - - plist_dict_set_item(request, "@VersionInfo", plist_new_string(TSS_CLIENT_VERSION_STRING)); - char* guid = generate_guid(); - if (guid) { - plist_dict_set_item(request, "@UUID", plist_new_string(guid)); - free(guid); - } - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return request; -} - -int tss_request_add_local_policy_tags(plist_t request, plist_t parameters) -{ - plist_dict_set_item(request, "@ApImg4Ticket", plist_new_bool(1)); - - if (_plist_dict_copy_bool(request, parameters, "Ap,LocalBoot", NULL) < 0) { - error("ERROR: Unable to find required Ap,LocalBoot in parameters\n"); - return -1; - } - - if (_plist_dict_copy_item(request, parameters, "Ap,LocalPolicy", NULL) < 0) { - error("ERROR: Unable to find required Ap,LocalPolicy in parameters\n"); - return -1; - } - - if (_plist_dict_copy_data(request, parameters, "Ap,NextStageIM4MHash", NULL) < 0) { - error("ERROR: Unable to find required Ap,NextStageIM4MHash in parameters\n"); - return -1; - } - - _plist_dict_copy_data(request, parameters, "Ap,RecoveryOSPolicyNonceHash", NULL); - _plist_dict_copy_data(request, parameters, "Ap,VolumeUUID", NULL); - _plist_dict_copy_uint(request, parameters, "ApECID", NULL); - _plist_dict_copy_uint(request, parameters, "ApChipID", NULL); - _plist_dict_copy_uint(request, parameters, "ApBoardID", NULL); - _plist_dict_copy_uint(request, parameters, "ApSecurityDomain", NULL); - _plist_dict_copy_data(request, parameters, "ApNonce", NULL); - - if (!plist_dict_get_item(request, "ApSecurityMode")) { - /* copy from parameters if available */ - if (_plist_dict_copy_bool(request, parameters, "ApSecurityMode", NULL) < 0) { - error("ERROR: Unable to find required ApSecurityMode in parameters\n"); - return -1; - } - } - if (!plist_dict_get_item(request, "ApProductionMode")) { - /* copy from parameters if available */ - if (_plist_dict_copy_bool(request, parameters, "ApProductionMode", NULL) < 0) { - error("ERROR: Unable to find required ApProductionMode in parameters\n"); - return -1; - } - } - - return 0; -} - -int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity, bool include_manifest) -{ - plist_t node = NULL; - - if (_plist_dict_copy_data(parameters, build_identity, "UniqueBuildID", NULL) < 0) { - error("ERROR: Unable to find UniqueBuildID node\n"); - return -1; - } - - _plist_dict_copy_string(parameters, build_identity, "Ap,OSLongVersion", NULL); - - if (_plist_dict_copy_uint(parameters, build_identity, "ApChipID", NULL) < 0) {; - error("ERROR: Unable to find ApChipID node\n"); - return -1; - } - - if (_plist_dict_copy_uint(parameters, build_identity, "ApBoardID", NULL) < 0) { - error("ERROR: Unable to find ApBoardID node\n"); - return -1; - } - - _plist_dict_copy_uint(parameters, build_identity, "ApSecurityDomain", NULL); - _plist_dict_copy_uint(parameters, build_identity, "BMU,BoardID", NULL); - _plist_dict_copy_uint(parameters, build_identity, "BMU,ChipID", NULL); - - if (_plist_dict_copy_uint(parameters, build_identity, "BbChipID", NULL) < 0) { - debug("NOTE: Unable to find BbChipID node\n"); - } - - if (_plist_dict_copy_data(parameters, build_identity, "BbProvisioningManifestKeyHash", NULL) < 0) { - debug("NOTE: Unable to find BbProvisioningManifestKeyHash node\n"); - } - - if (_plist_dict_copy_data(parameters, build_identity, "BbActivationManifestKeyHash", NULL) < 0) { - debug("NOTE: Unable to find BbActivationManifestKeyHash node\n"); - } - - if (_plist_dict_copy_data(parameters, build_identity, "BbCalibrationManifestKeyHash", NULL) < 0) { - debug("NOTE: Unable to find BbCalibrationManifestKeyHash node\n"); - } - - if (_plist_dict_copy_data(parameters, build_identity, "BbFactoryActivationManifestKeyHash", NULL) < 0) { - debug("NOTE: Unable to find BbFactoryActivationManifestKeyHash node\n"); - } - - if (_plist_dict_copy_data(parameters, build_identity, "BbFDRSecurityKeyHash", NULL) < 0) { - debug("NOTE: Unable to find BbFDRSecurityKeyHash node\n"); - } - - /* BbSkeyId - Used by XMM 6180/GSM */ - if (_plist_dict_copy_data(parameters, build_identity, "BbSkeyId", NULL) < 0) { - debug("NOTE: Unable to find BbSkeyId node\n"); - } - - /* SE,ChipID - Used for SE firmware request */ - _plist_dict_copy_uint(parameters, build_identity, "SE,ChipID", NULL); - - /* Savage,ChipID - Used for Savage firmware request */ - _plist_dict_copy_uint(parameters, build_identity, "Savage,ChipID", NULL); - - /* add Savage,PatchEpoch - Used for Savage firmware request */ - _plist_dict_copy_uint(parameters, build_identity, "Savage,PatchEpoch", NULL); - - /* Yonkers,BoardID - Used for Yonkers firmware request */ - _plist_dict_copy_uint(parameters, build_identity, "Yonkers,BoardID", NULL); - - /* Yonkers,ChipID - Used for Yonkers firmware request */ - _plist_dict_copy_uint(parameters, build_identity, "Yonkers,ChipID", NULL); - - /* add Yonkers,PatchEpoch - Used for Yonkers firmware request */ - _plist_dict_copy_uint(parameters, build_identity, "Yonkers,PatchEpoch", NULL); - - _plist_dict_copy_uint(parameters, build_identity, "Rap,BoardID", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Rap,ChipID", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Rap,SecurityDomain", NULL); - - _plist_dict_copy_uint(parameters, build_identity, "Baobab,BoardID", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Baobab,ChipID", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Baobab,ManifestEpoch", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Baobab,SecurityDomain", NULL); - - _plist_dict_copy_uint(parameters, build_identity, "eUICC,ChipID", NULL); - - _plist_dict_copy_uint(parameters, build_identity, "NeRDEpoch", NULL); - _plist_dict_copy_data(parameters, build_identity, "PearlCertificationRootPub", NULL); - - _plist_dict_copy_uint(parameters, build_identity, "Timer,BoardID,1", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Timer,BoardID,2", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Timer,ChipID,1", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Timer,ChipID,2", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Timer,SecurityDomain,1", NULL); - _plist_dict_copy_uint(parameters, build_identity, "Timer,SecurityDomain,2", NULL); - - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,ChipID", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,Type", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,SubType", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,ProductClass", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,UseProductClass", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,NonceDomain", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,Version", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,PreauthorizationVersion", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,FakeRoot", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,SystemOS", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,SystemVolume", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,SystemTrustCache", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,AppOS", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,AppVolume", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,AppTrustCache", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,MobileAssetBrainOS", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,MobileAssetBrainVolume", NULL); - _plist_dict_copy_item(parameters, build_identity, "Cryptex1,MobileAssetBrainTrustCache", NULL); - - _plist_dict_copy_item(parameters, build_identity, "USBPortController1,BoardID", NULL); - _plist_dict_copy_item(parameters, build_identity, "USBPortController1,ChipID", NULL); - _plist_dict_copy_item(parameters, build_identity, "USBPortController1,SecurityDomain", NULL); - - node = plist_dict_get_item(build_identity, "Info"); - if (node) { - _plist_dict_copy_bool(parameters, node, "RequiresUIDMode", NULL); - } - - if (include_manifest) { - /* add build identity manifest dictionary */ - node = plist_dict_get_item(build_identity, "Manifest"); - if (!node || plist_get_node_type(node) != PLIST_DICT) { - error("ERROR: Unable to find Manifest node\n"); - return -1; - } - plist_dict_set_item(parameters, "Manifest", plist_copy(node)); - } - - return 0; -} - -int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) -{ - if (!parameters) { - error("ERROR: Missing required AP parameters\n"); - return -1; - } - - _plist_dict_copy_string(request, parameters, "Ap,OSLongVersion", NULL); - - if (_plist_dict_copy_data(request, parameters, "ApNonce", NULL) < 0) { - error("ERROR: Unable to find required ApNonce in parameters\n"); - return -1; - } - - plist_dict_set_item(request, "@ApImg4Ticket", plist_new_bool(1)); - - if (!plist_dict_get_item(request, "ApSecurityMode")) { - /* copy from parameters if available */ - if (_plist_dict_copy_bool(request, parameters, "ApSecurityMode", NULL) < 0) { - error("ERROR: Unable to find required ApSecurityMode in parameters\n"); - return -1; - } - } - if (!plist_dict_get_item(request, "ApProductionMode")) { - /* ApProductionMode */ - if (_plist_dict_copy_bool(request, parameters, "ApProductionMode", NULL) < 0) { - error("ERROR: Unable to find required ApProductionMode in parameters\n"); - return -1; - } - } - - _plist_dict_copy_data(request, parameters, "SepNonce", "ApSepNonce"); - _plist_dict_copy_uint(request, parameters, "NeRDEpoch", NULL); - _plist_dict_copy_data(request, parameters, "PearlCertificationRootPub", NULL); - - if (plist_dict_get_item(parameters, "UID_MODE")) { - _plist_dict_copy_item(request, parameters, "UID_MODE", NULL); - } else if (_plist_dict_get_bool(parameters, "RequiresUIDMode")) { - // The logic here is missing why this value is expected to be 'false' - plist_dict_set_item(request, "UID_MODE", plist_new_bool(0)); - } - - // FIXME: I didn't understand yet when this value is set, so for now we use a workaround - if (plist_dict_get_item(parameters, "ApSikaFuse")) { - _plist_dict_copy_item(request, parameters, "Ap,SikaFuse", "ApSikaFuse"); - } else if (_plist_dict_get_bool(parameters, "RequiresUIDMode")) { - // Workaround: We have only seen Ap,SikaFuse together with UID_MODE - plist_dict_set_item(request, "Ap,SikaFuse", plist_new_int(0)); - } - - return 0; -} - -int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) -{ - if (!parameters) { - error("ERROR: Missing required AP parameters\n"); - return -1; - } - - if (_plist_dict_copy_data(request, parameters, "ApNonce", NULL) < 0) { - error("WARNING: Unable to find ApNonce in parameters\n"); - } - - plist_dict_set_item(request, "@APTicket", plist_new_bool(1)); - - if (_plist_dict_copy_uint(request, parameters, "ApBoardID", NULL) < 0) { - error("ERROR: Unable to find required ApBoardID in request\n"); - return -1; - } - - if (_plist_dict_copy_uint(request, parameters, "ApChipID", NULL) < 0) { - error("ERROR: Unable to find required ApChipID in request\n"); - return -1; - } - - if (_plist_dict_copy_uint(request, parameters, "ApSecurityDomain", NULL) < 0) { - error("ERROR: Unable to find required ApSecurityDomain in request\n"); - return -1; - } - - if (_plist_dict_copy_bool(request, parameters, "ApProductionMode", NULL) < 0) { - error("ERROR: Unable to find required ApProductionMode in parameters\n"); - return -1; - } - - return 0; -} - -int tss_request_add_common_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - _plist_dict_copy_uint(request, parameters, "ApECID", NULL); - _plist_dict_copy_data(request, parameters, "UniqueBuildID", NULL); - _plist_dict_copy_uint(request, parameters, "ApChipID", NULL); - _plist_dict_copy_uint(request, parameters, "ApBoardID", NULL); - _plist_dict_copy_uint(request, parameters, "ApSecurityDomain", NULL); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -static void tss_entry_apply_restore_request_rules(plist_t tss_entry, plist_t parameters, plist_t rules) -{ - if (!tss_entry || !rules) { - return; - } - if (plist_get_node_type(tss_entry) != PLIST_DICT) { - return; - } - if (plist_get_node_type(rules) != PLIST_ARRAY) { - return; - } - - uint32_t i; - for (i = 0; i < plist_array_get_size(rules); i++) { - plist_t rule = plist_array_get_item(rules, i); - plist_t conditions = plist_dict_get_item(rule, "Conditions"); - plist_dict_iter iter = NULL; - plist_dict_new_iter(conditions, &iter); - char* key = NULL; - plist_t value = NULL; - plist_t value2 = NULL; - int conditions_fulfilled = 1; - while (conditions_fulfilled) { - plist_dict_next_item(conditions, iter, &key, &value); - if (key == NULL) - break; - if (!strcmp(key, "ApRawProductionMode")) { - value2 = plist_dict_get_item(parameters, "ApProductionMode"); - } else if (!strcmp(key, "ApCurrentProductionMode")) { - value2 = plist_dict_get_item(parameters, "ApProductionMode"); - } else if (!strcmp(key, "ApRawSecurityMode")) { - value2 = plist_dict_get_item(parameters, "ApSecurityMode"); - } else if (!strcmp(key, "ApRequiresImage4")) { - value2 = plist_dict_get_item(parameters, "ApSupportsImg4"); - } else if (!strcmp(key, "ApDemotionPolicyOverride")) { - value2 = plist_dict_get_item(parameters, "DemotionPolicy"); - } else if (!strcmp(key, "ApInRomDFU")) { - value2 = plist_dict_get_item(parameters, "ApInRomDFU"); - } else { - error("WARNING: Unhandled condition '%s' while parsing RestoreRequestRules\n", key); - value2 = NULL; - } - if (value2) { - conditions_fulfilled = plist_compare_node_value(value, value2); - } else { - conditions_fulfilled = 0; - } - free(key); - } - free(iter); - iter = NULL; - - if (!conditions_fulfilled) { - continue; - } - - plist_t actions = plist_dict_get_item(rule, "Actions"); - plist_dict_new_iter(actions, &iter); - while (1) { - plist_dict_next_item(actions, iter, &key, &value); - if (key == NULL) - break; - uint8_t bv = 255; - plist_get_bool_val(value, &bv); - if (bv != 255) { - value2 = plist_dict_get_item(tss_entry, key); - if (value2) { - plist_dict_remove_item(tss_entry, key); - } - debug("DEBUG: Adding %s=%s to TSS entry\n", key, (bv) ? "true" : "false"); - plist_dict_set_item(tss_entry, key, plist_new_bool(bv)); - } - free(key); - } - } -} - -int tss_request_add_ap_recovery_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - /* loop over components from build manifest */ - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: Unable to find restore manifest\n"); - return -1; - } - - /* add components to request */ - char* key = NULL; - plist_t manifest_entry = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (1) { - free(key); - key = NULL; - plist_dict_next_item(manifest_node, iter, &key, &manifest_entry); - if (key == NULL) - break; - if (!manifest_entry || plist_get_node_type(manifest_entry) != PLIST_DICT) { - error("ERROR: Unable to fetch BuildManifest entry\n"); - free(key); - return -1; - } - - /* do not populate BaseBandFirmware, only in basebaseband request */ - if ((strcmp(key, "BasebandFirmware") == 0)) { - continue; - } - - // Compared to ac2, not needed for RecoveryOSRootTicket - if ((strcmp(key, "SE,UpdatePayload") == 0)) { - continue; - } - if ((strcmp(key, "BaseSystem") == 0)) { - continue; - } - if ((strcmp(key, "ANS") == 0)) { - continue; - } - if ((strcmp(key, "Ap,AudioBootChime") == 0)) { - continue; - } - if ((strcmp(key, "Ap,CIO") == 0)) { - continue; - } - if ((strcmp(key, "Ap,RestoreCIO") == 0)) { - continue; - } - if ((strcmp(key, "Ap,RestoreTMU") == 0)) { - continue; - } - if ((strcmp(key, "Ap,TMU") == 0)) { - continue; - } - if ((strcmp(key, "Ap,rOSLogo1") == 0)) { - continue; - } - if ((strcmp(key, "Ap,rOSLogo2") == 0)) { - continue; - } - if ((strcmp(key, "AppleLogo") == 0)) { - continue; - } - if ((strcmp(key, "DCP") == 0)) { - continue; - } - if ((strcmp(key, "LLB") == 0)) { - continue; - } - if ((strcmp(key, "RecoveryMode") == 0)) { - continue; - } - if ((strcmp(key, "RestoreANS") == 0)) { - continue; - } - if ((strcmp(key, "RestoreDCP") == 0)) { - continue; - } - if ((strcmp(key, "RestoreDeviceTree") == 0)) { - continue; - } - if ((strcmp(key, "RestoreKernelCache") == 0)) { - continue; - } - if ((strcmp(key, "RestoreLogo") == 0)) { - continue; - } - if ((strcmp(key, "RestoreRamDisk") == 0)) { - continue; - } - if ((strcmp(key, "RestoreSEP") == 0)) { - continue; - } - if ((strcmp(key, "SEP") == 0)) { - continue; - } - if ((strcmp(key, "ftap") == 0)) { - continue; - } - if ((strcmp(key, "ftsp") == 0)) { - continue; - } - if ((strcmp(key, "iBEC") == 0)) { - continue; - } - if ((strcmp(key, "iBSS") == 0)) { - continue; - } - if ((strcmp(key, "rfta") == 0)) { - continue; - } - if ((strcmp(key, "rfts") == 0)) { - continue; - } - - /* FIXME: only used with diagnostics firmware */ - if (strcmp(key, "Diags") == 0) { - continue; - } - - plist_t info_dict = plist_dict_get_item(manifest_entry, "Info"); - if (!info_dict) { - continue; - } - - if (_plist_dict_get_bool(parameters, "_OnlyFWComponents")) { - if (!_plist_dict_get_bool(manifest_entry, "Trusted")) { - debug("DEBUG: %s: Skipping '%s' as it is not trusted\n", __func__, key); - continue; - } - - if (!_plist_dict_get_bool(info_dict, "IsFirmwarePayload") - && !_plist_dict_get_bool(info_dict, "IsSecondaryFirmwarePayload") - && !_plist_dict_get_bool(info_dict, "IsFUDFirmware") - && !_plist_dict_get_bool(info_dict, "IsLoadedByiBoot") - && !_plist_dict_get_bool(info_dict, "IsEarlyAccessFirmware") - && !_plist_dict_get_bool(info_dict, "IsiBootEANFirmware") - && !_plist_dict_get_bool(info_dict, "IsiBootNonEssentialFirmware")) - { - debug("DEBUG: %s: Skipping '%s' as it is not a firmware payload\n", __func__, key); - continue; - } - } - - /* copy this entry */ - plist_t tss_entry = plist_copy(manifest_entry); - - /* remove obsolete Info node */ - plist_dict_remove_item(tss_entry, "Info"); - - /* handle RestoreRequestRules */ - plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules"); - if (rules) { - debug("DEBUG: Applying restore request rules for entry %s\n", key); - tss_entry_apply_restore_request_rules(tss_entry, parameters, rules); - } - - /* Make sure we have a Digest key for Trusted items even if empty */ - if (_plist_dict_get_bool(manifest_entry, "Trusted") && !plist_dict_get_item(manifest_entry, "Digest")) { - debug("DEBUG: No Digest data, using empty value for entry %s\n", key); - plist_dict_set_item(tss_entry, "Digest", plist_new_data(NULL, 0)); - } - - /* finally add entry to request */ - plist_dict_set_item(request, key, tss_entry); - } - free(key); - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - /* loop over components from build manifest */ - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: Unable to find restore manifest\n"); - return -1; - } - - /* add components to request */ - char* key = NULL; - plist_t manifest_entry = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (1) { - free(key); - key = NULL; - plist_dict_next_item(manifest_node, iter, &key, &manifest_entry); - if (key == NULL) - break; - if (!manifest_entry || plist_get_node_type(manifest_entry) != PLIST_DICT) { - error("ERROR: Unable to fetch BuildManifest entry\n"); - free(key); - return -1; - } - - /* do not populate BaseBandFirmware, only in basebaseband request */ - if ((strcmp(key, "BasebandFirmware") == 0)) { - continue; - } - - // Compared to ac2, not needed - if ((strcmp(key, "SE,UpdatePayload") == 0)) { - continue; - } - - // Compared to ac2, not needed - if ((strcmp(key, "BaseSystem") == 0)) { - continue; - } - - /* FIXME: only used with diagnostics firmware */ - if (strcmp(key, "Diags") == 0) { - continue; - } - - plist_t info_dict = plist_dict_get_item(manifest_entry, "Info"); - if (!info_dict) { - continue; - } - - if (_plist_dict_get_bool(parameters, "ApSupportsImg4")) { - if (!plist_dict_get_item(info_dict, "RestoreRequestRules")) { - debug("DEBUG: %s: Skipping '%s' as it doesn't have RestoreRequestRules\n", __func__, key); - continue; - } - } - - int is_fw_payload = _plist_dict_get_bool(info_dict, "IsFirmwarePayload") - || _plist_dict_get_bool(info_dict, "IsSecondaryFirmwarePayload") - || _plist_dict_get_bool(info_dict, "IsFUDFirmware") - || _plist_dict_get_bool(info_dict, "IsLoadedByiBoot") - || _plist_dict_get_bool(info_dict, "IsEarlyAccessFirmware") - || _plist_dict_get_bool(info_dict, "IsiBootEANFirmware") - || _plist_dict_get_bool(info_dict, "IsiBootNonEssentialFirmware"); - - if (_plist_dict_get_bool(parameters, "_OnlyFWOrTrustedComponents")) { - if (!_plist_dict_get_bool(manifest_entry, "Trusted") && !is_fw_payload) { - debug("DEBUG: %s: Skipping '%s' as it is neither firmware payload nor trusted\n", __func__, key); - continue; - } - } else if (_plist_dict_get_bool(parameters, "_OnlyFWComponents")) { - if (!_plist_dict_get_bool(manifest_entry, "Trusted")) { - debug("DEBUG: %s: Skipping '%s' as it is not trusted\n", __func__, key); - continue; - } - if (!is_fw_payload) { - debug("DEBUG: %s: Skipping '%s' as it is not a firmware payload\n", __func__, key); - continue; - } - } - - /* skip components with IsFTAB:true */ - if (_plist_dict_get_bool(info_dict, "IsFTAB")) { - debug("DEBUG: %s: Skipping FTAB component '%s'\n", __func__, key); - continue; - } - - /* copy this entry */ - plist_t tss_entry = plist_copy(manifest_entry); - - /* remove obsolete Info node */ - plist_dict_remove_item(tss_entry, "Info"); - - /* handle RestoreRequestRules */ - plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules"); - if (rules) { - debug("DEBUG: Applying restore request rules for entry %s\n", key); - tss_entry_apply_restore_request_rules(tss_entry, parameters, rules); - } - - /* Make sure we have a Digest key for Trusted items even if empty */ - if (_plist_dict_get_bool(manifest_entry, "Trusted") && !plist_dict_get_item(manifest_entry, "Digest")) { - debug("DEBUG: No Digest data, using empty value for entry %s\n", key); - plist_dict_set_item(tss_entry, "Digest", plist_new_data(NULL, 0)); - } - - /* finally add entry to request */ - plist_dict_set_item(request, key, tss_entry); - } - free(key); - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t node = NULL; - - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - - _plist_dict_copy_uint(request, parameters, "BbChipID", NULL); - _plist_dict_copy_data(request, parameters, "BbProvisioningManifestKeyHash", NULL); - /* BbActivationManifestKeyHash - Used by Qualcomm MDM6610 */ - _plist_dict_copy_data(request, parameters, "BbActivationManifestKeyHash", NULL); - _plist_dict_copy_data(request, parameters, "BbCalibrationManifestKeyHash", NULL); - _plist_dict_copy_data(request, parameters, "BbFactoryActivationManifestKeyHash", NULL); - _plist_dict_copy_data(request, parameters, "BbFDRSecurityKeyHash", NULL); - /* BbSkeyId - Used by XMM 6180/GSM */ - _plist_dict_copy_data(request, parameters, "BbSkeyId", NULL); - _plist_dict_copy_data(request, parameters, "BbNonce", NULL); - _plist_dict_copy_uint(request, parameters, "BbGoldCertId", NULL); - - uint64_t bb_chip_id = _plist_dict_get_uint(request, "BbChipID"); - int32_t bb_cert_id = (int32_t)_plist_dict_get_uint(request, "BbGoldCertId"); - - if (_plist_dict_copy_data(request, parameters, "BbSNUM", NULL) < 0) { - error("ERROR: Unable to find required BbSNUM in parameters\n"); - return -1; - } - - /* BasebandFirmware */ - node = plist_access_path(parameters, 2, "Manifest", "BasebandFirmware"); - if (!node || plist_get_node_type(node) != PLIST_DICT) { - error("ERROR: Unable to get BasebandFirmware node\n"); - return -1; - } - plist_t bbfwdict = plist_copy(node); - node = NULL; - if (plist_dict_get_item(bbfwdict, "Info")) { - plist_dict_remove_item(bbfwdict, "Info"); - } - - if (bb_chip_id == 0x68) { - /* depending on the BasebandCertId remove certain nodes */ - if (bb_cert_id == 0x26F3FACC || bb_cert_id == 0x5CF2EC4E || bb_cert_id == 0x8399785A) { - plist_dict_remove_item(bbfwdict, "PSI2-PartialDigest"); - plist_dict_remove_item(bbfwdict, "RestorePSI2-PartialDigest"); - } else { - plist_dict_remove_item(bbfwdict, "PSI-PartialDigest"); - plist_dict_remove_item(bbfwdict, "RestorePSI-PartialDigest"); - } - } - - plist_dict_set_item(request, "BasebandFirmware", bbfwdict); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - - if (_plist_dict_copy_uint(request, parameters, "SE,ChipID", NULL) < 0) { - error("ERROR: %s: Unable to find required SE,ChipID in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_data(request, parameters, "SE,ID", NULL) < 0) { - error("ERROR: %s: Unable to find required SE,ID in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_data(request, parameters, "SE,Nonce", NULL) < 0) { - error("ERROR: %s: Unable to find required SE,Nonce in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_data(request, parameters, "SE,RootKeyIdentifier", NULL) < 0) { - error("ERROR: %s: Unable to find required SE,RootKeyIdentifier in parameters\n", __func__); - return -1; - } - - /* 'IsDev' determines whether we have Production or Development */ - uint8_t is_dev = _plist_dict_get_bool(parameters, "SE,IsDev"); - - /* add SE,* components from build manifest to request */ - char* key = NULL; - plist_t manifest_entry = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (1) { - free(key); - key = NULL; - plist_dict_next_item(manifest_node, iter, &key, &manifest_entry); - if (key == NULL) - break; - if (!manifest_entry || plist_get_node_type(manifest_entry) != PLIST_DICT) { - error("ERROR: Unable to fetch BuildManifest entry\n"); - free(key); - return -1; - } - - if (strncmp(key, "SE,", 3)) { - continue; - } - - /* copy this entry */ - plist_t tss_entry = plist_copy(manifest_entry); - - /* remove Info node */ - plist_dict_remove_item(tss_entry, "Info"); - - /* remove Development or Production key/hash node */ - if (is_dev) { - if (plist_dict_get_item(tss_entry, "ProductionCMAC")) - plist_dict_remove_item(tss_entry, "ProductionCMAC"); - if (plist_dict_get_item(tss_entry, "ProductionUpdatePayloadHash")) - plist_dict_remove_item(tss_entry, "ProductionUpdatePayloadHash"); - } else { - if (plist_dict_get_item(tss_entry, "DevelopmentCMAC")) - plist_dict_remove_item(tss_entry, "DevelopmentCMAC"); - if (plist_dict_get_item(tss_entry, "DevelopmentUpdatePayloadHash")) - plist_dict_remove_item(tss_entry, "DevelopmentUpdatePayloadHash"); - } - - /* add entry to request */ - plist_dict_set_item(request, key, tss_entry); - } - free(key); - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - /* fallback in case no @SE2,Ticket or @SE,Ticket was provided */ - if (!plist_dict_get_item(request, "@SE2,Ticket") && !plist_dict_get_item(request, "@SE,Ticket")) { - plist_dict_set_item(request, "@SE,Ticket", plist_new_bool(1)); - } - - return 0; -} - -int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t overrides, char **component_name) -{ - plist_t node = NULL; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the Savage,Ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@Savage,Ticket", plist_new_bool(1)); - - if (_plist_dict_copy_data(request, parameters, "Savage,UID", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,UID in parameters\n", __func__); - return -1; - } - - /* add SEP */ - node = plist_access_path(manifest_node, 2, "SEP", "Digest"); - if (!node) { - error("ERROR: Unable to get SEP digest from manifest\n"); - return -1; - } - plist_t dict = plist_new_dict(); - plist_dict_set_item(dict, "Digest", plist_copy(node)); - plist_dict_set_item(request, "SEP", dict); - - if (_plist_dict_copy_uint(request, parameters, "Savage,PatchEpoch", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,PatchEpoch in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_uint(request, parameters, "Savage,ChipID", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,ChipID in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_bool(request, parameters, "Savage,AllowOfflineBoot", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,AllowOfflineBoot in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_bool(request, parameters, "Savage,ReadFWKey", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,ReadFWKey in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_bool(request, parameters, "Savage,ProductionMode", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,ProductionMode in parameters\n", __func__); - return -1; - } - - const char *comp_name = NULL; - uint8_t isprod = _plist_dict_get_bool(request, "Savage,ProductionMode"); - - /* get the right component name */ - comp_name = (isprod) ? "Savage,B0-Prod-Patch" : "Savage,B0-Dev-Patch"; - node = plist_dict_get_item(parameters, "Savage,Revision"); - if (node && (plist_get_node_type(node) == PLIST_DATA)) { - unsigned char *savage_rev = NULL; - uint64_t savage_rev_len = 0; - plist_get_data_val(node, (char**)&savage_rev, &savage_rev_len); - if (savage_rev_len > 0) { - if (((savage_rev[0] | 0x10) & 0xF0) == 0x30) { - comp_name = (isprod) ? "Savage,B2-Prod-Patch" : "Savage,B2-Dev-Patch"; - } else if ((savage_rev[0] & 0xF0) == 0xA0) { - comp_name = (isprod) ? "Savage,BA-Prod-Patch" : "Savage,BA-Dev-Patch"; - } - } - free(savage_rev); - } - - /* add Savage,B?-*-Patch */ - node = plist_dict_get_item(manifest_node, comp_name); - if (!node) { - error("ERROR: Unable to get %s entry from manifest\n", comp_name); - return -1; - } - dict = plist_copy(node); - plist_dict_remove_item(dict, "Info"); - plist_dict_set_item(request, comp_name, dict); - - if (component_name) { - *component_name = strdup(comp_name); - } - - if (_plist_dict_copy_data(request, parameters, "Savage,Nonce", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,Nonce in parameters\n", __func__); - return -1; - } - - if (_plist_dict_copy_bool(request, parameters, "Savage,ReadECKey", NULL) < 0) { - error("ERROR: %s: Unable to find required Savage,ReadECKey in parameters\n", __func__); - return -1; - } - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t overrides, char **component_name) -{ - plist_t node = NULL; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the Savage,Ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@Yonkers,Ticket", plist_new_bool(1)); - - /* add SEP */ - node = plist_access_path(manifest_node, 2, "SEP", "Digest"); - if (!node) { - error("ERROR: Unable to get SEP digest from manifest\n"); - return -1; - } - plist_t dict = plist_new_dict(); - plist_dict_set_item(dict, "Digest", plist_copy(node)); - plist_dict_set_item(request, "SEP", dict); - - { - static const char *keys[] = {"Yonkers,AllowOfflineBoot", "Yonkers,BoardID", "Yonkers,ChipID", "Yonkers,ECID", "Yonkers,Nonce", "Yonkers,PatchEpoch", "Yonkers,ProductionMode", "Yonkers,ReadECKey", "Yonkers,ReadFWKey", }; - int i; - for (i = 0; i < (int)(sizeof(keys) / sizeof(keys[0])); ++i) { - node = plist_dict_get_item(parameters, keys[i]); - if (!node) { - error("ERROR: %s: Unable to find required %s in parameters\n", __func__, keys[i]); - } - plist_dict_set_item(request, keys[i], plist_copy(node)); - node = NULL; - } - } - - char *comp_name = NULL; - plist_t comp_node = NULL; - uint8_t isprod = _plist_dict_get_bool(parameters, "Yonkers,ProductionMode"); - uint64_t fabrevision = _plist_dict_get_uint(parameters, "Yonkers,FabRevision"); - - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (iter) { - node = NULL; - comp_name = NULL; - plist_dict_next_item(manifest_node, iter, &comp_name, &node); - if (comp_name == NULL) { - node = NULL; - break; - } - if (strncmp(comp_name, "Yonkers,", 8) == 0) { - int target_node = 1; - plist_t sub_node; - if ((sub_node = plist_dict_get_item(node, "EPRO")) != NULL && plist_get_node_type(sub_node) == PLIST_BOOLEAN) { - uint8_t b = 0; - plist_get_bool_val(sub_node, &b); - target_node &= ((isprod) ? b : !b); - } - if ((sub_node = plist_dict_get_item(node, "FabRevision")) != NULL && plist_get_node_type(sub_node) == PLIST_UINT) { - uint64_t v = 0; - plist_get_uint_val(sub_node, &v); - target_node &= (v == fabrevision); - } - if (target_node) { - comp_node = node; - break; - } - } - free(comp_name); - } - free(iter); - - if (comp_name == NULL) { - error("ERROR: No Yonkers node for %s/%lu\n", (isprod) ? "Production" : "Development", (unsigned long)fabrevision); - return -1; - } - - /* add Yonkers,SysTopPatch* */ - if (comp_node != NULL) { - plist_t comp_dict = plist_copy(comp_node); - plist_dict_remove_item(comp_dict, "Info"); - plist_dict_set_item(request, comp_name, comp_dict); - } - - if (component_name) { - *component_name = comp_name; - } else { - free(comp_name); - } - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_vinyl_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t node = NULL; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the eUICC,Ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@eUICC,Ticket", plist_new_bool(1)); - - _plist_dict_copy_bool(request, parameters, "eUICC,ApProductionMode", "ApProductionMode"); - _plist_dict_copy_uint(request, parameters, "eUICC,ChipID", NULL); - _plist_dict_copy_data(request, parameters, "eUICC,EID", NULL); - _plist_dict_copy_data(request, parameters, "eUICC,RootKeyIdentifier", NULL); - - if (!plist_dict_get_item(request, "eUICC,Gold")) { - plist_t n = plist_access_path(parameters, 2, "Manifest", "eUICC,Gold"); - if (n) { - plist_t p = plist_new_dict(); - _plist_dict_copy_data(p, n, "Digest", NULL); - plist_dict_set_item(request, "eUICC,Gold", p); - } - } - - if (!plist_dict_get_item(request, "eUICC,Main")) { - plist_t n = plist_access_path(parameters, 2, "Manifest", "eUICC,Main"); - if (n) { - plist_t p = plist_new_dict(); - _plist_dict_copy_data(p, n, "Digest", NULL); - plist_dict_set_item(request, "eUICC,Main", p); - } - } - - /* set Nonce for eUICC,Gold component */ - node = plist_dict_get_item(parameters, "EUICCGoldNonce"); - if (node) { - plist_t n = plist_dict_get_item(request, "eUICC,Gold"); - if (n) { - plist_dict_set_item(n, "Nonce", plist_copy(node)); - } - } - - /* set Nonce for eUICC,Main component */ - node = plist_dict_get_item(parameters, "EUICCMainNonce"); - if (node) { - plist_t n = plist_dict_get_item(request, "eUICC,Main"); - if (n) { - plist_dict_set_item(n, "Nonce", plist_copy(node)); - } - } - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_rose_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t node = NULL; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the Rap,Ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@Rap,Ticket", plist_new_bool(1)); - - _plist_dict_copy_uint(request, parameters, "Rap,BoardID", NULL); - _plist_dict_copy_uint(request, parameters, "Rap,ChipID", NULL); - _plist_dict_copy_uint(request, parameters, "Rap,ECID", NULL); - _plist_dict_copy_data(request, parameters, "Rap,Nonce", NULL); - _plist_dict_copy_bool(request, parameters, "Rap,ProductionMode", NULL); - _plist_dict_copy_uint(request, parameters, "Rap,SecurityDomain", NULL); - _plist_dict_copy_bool(request, parameters, "Rap,SecurityMode", NULL); - _plist_dict_copy_data(request, parameters, "Rap,FdrRootCaDigest", NULL); - - char *comp_name = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (iter) { - node = NULL; - comp_name = NULL; - plist_dict_next_item(manifest_node, iter, &comp_name, &node); - if (comp_name == NULL) { - node = NULL; - break; - } - if (strncmp(comp_name, "Rap,", 4) == 0) { - plist_t manifest_entry = plist_copy(node); - - /* handle RestoreRequestRules */ - plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules"); - if (rules) { - debug("DEBUG: Applying restore request rules for entry %s\n", comp_name); - tss_entry_apply_restore_request_rules(manifest_entry, parameters, rules); - } - - /* Make sure we have a Digest key for Trusted items even if empty */ - if (_plist_dict_get_bool(manifest_entry, "Trusted") && !plist_dict_get_item(manifest_entry, "Digest")) { - debug("DEBUG: No Digest data, using empty value for entry %s\n", comp_name); - plist_dict_set_item(manifest_entry, "Digest", plist_new_data(NULL, 0)); - } - - plist_dict_remove_item(manifest_entry, "Info"); - - /* finally add entry to request */ - plist_dict_set_item(request, comp_name, manifest_entry); - } - free(comp_name); - } - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_veridian_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t node = NULL; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the BMU,Ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@BMU,Ticket", plist_new_bool(1)); - - _plist_dict_copy_uint(request, parameters, "BMU,BoardID", NULL); - _plist_dict_copy_uint(request, parameters, "BMU,ChipID", "ChipID"); - _plist_dict_copy_data(request, parameters, "BMU,Nonce", "Nonce"); - _plist_dict_copy_bool(request, parameters, "BMU,ProductionMode", "ProductionMode"); - _plist_dict_copy_uint(request, parameters, "BMU,UniqueID", "UniqueID"); - - char *comp_name = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (iter) { - node = NULL; - comp_name = NULL; - plist_dict_next_item(manifest_node, iter, &comp_name, &node); - if (comp_name == NULL) { - node = NULL; - break; - } - if (strncmp(comp_name, "BMU,", 4) == 0) { - plist_t manifest_entry = plist_copy(node); - - /* handle RestoreRequestRules */ - plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules"); - if (rules) { - debug("DEBUG: Applying restore request rules for entry %s\n", comp_name); - tss_entry_apply_restore_request_rules(manifest_entry, parameters, rules); - } - - /* Make sure we have a Digest key for Trusted items even if empty */ - if (_plist_dict_get_bool(manifest_entry, "Trusted") && !plist_dict_get_item(manifest_entry, "Digest")) { - debug("DEBUG: No Digest data, using empty value for entry %s\n", comp_name); - plist_dict_set_item(manifest_entry, "Digest", plist_new_data(NULL, 0)); - } - - plist_dict_remove_item(manifest_entry, "Info"); - - /* finally add entry to request */ - plist_dict_set_item(request, comp_name, manifest_entry); - } - free(comp_name); - } - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t node = NULL; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the Baobab,Ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - plist_dict_set_item(request, "@Baobab,Ticket", plist_new_bool(1)); - - _plist_dict_copy_uint(request, parameters, "Baobab,BoardID", NULL); - _plist_dict_copy_uint(request, parameters, "Baobab,ChipID", NULL); - _plist_dict_copy_data(request, parameters, "Baobab,ECID", NULL); - _plist_dict_copy_uint(request, parameters, "Baobab,Life", NULL); - _plist_dict_copy_uint(request, parameters, "Baobab,ManifestEpoch", NULL); - _plist_dict_copy_bool(request, parameters, "Baobab,ProductionMode", NULL); - _plist_dict_copy_uint(request, parameters, "Baobab,SecurityDomain", NULL); - _plist_dict_copy_data(request, parameters, "Baobab,UpdateNonce", NULL); - - uint8_t isprod = _plist_dict_get_bool(parameters, "Baobab,ProductionMode"); - - char *comp_name = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (iter) { - node = NULL; - comp_name = NULL; - plist_dict_next_item(manifest_node, iter, &comp_name, &node); - if (comp_name == NULL) { - node = NULL; - break; - } - if (strncmp(comp_name, "Baobab,", 7) == 0) { - plist_t manifest_entry = plist_copy(node); - - plist_dict_remove_item(manifest_entry, "Info"); - plist_dict_set_item(manifest_entry, "EPRO", plist_new_bool(isprod)); - - /* finally add entry to request */ - plist_dict_set_item(request, comp_name, manifest_entry); - } - free(comp_name); - } - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - return 0; -} - -int tss_request_add_timer_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - plist_t node = NULL; - uint32_t tag = 0; - - plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); - if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); - return -1; - } - - /* add tags indicating we want to get the Timer ticket */ - plist_dict_set_item(request, "@BBTicket", plist_new_bool(1)); - - node = plist_dict_get_item(parameters, "TicketName"); - if (!node) { - error("ERROR: %s: Missing TicketName\n", __func__); - return -1; - } - char key[64]; - sprintf(key, "@%s", plist_get_string_ptr(node, NULL)); - - plist_dict_set_item(request, key, plist_new_bool(1)); - - tag = (uint32_t)_plist_dict_get_uint(parameters, "TagNumber"); - - sprintf(key, "Timer,BoardID,%u", tag); - _plist_dict_copy_uint(request, parameters, key, NULL); - - sprintf(key, "Timer,ChipID,%u", tag); - _plist_dict_copy_uint(request, parameters, key, NULL); - - sprintf(key, "Timer,SecurityDomain,%u", tag); - _plist_dict_copy_uint(request, parameters, key, NULL); - - sprintf(key, "Timer,SecurityMode,%u", tag); - _plist_dict_copy_bool(request, parameters, key, NULL); - - sprintf(key, "Timer,ProductionMode,%u", tag); - _plist_dict_copy_bool(request, parameters, key, NULL); - - sprintf(key, "Timer,ECID,%u", tag); - _plist_dict_copy_uint(request, parameters, key, NULL); - - sprintf(key, "Timer,Nonce,%u", tag); - _plist_dict_copy_data(request, parameters, key, NULL); - - char *comp_name = NULL; - plist_dict_iter iter = NULL; - plist_dict_new_iter(manifest_node, &iter); - while (iter) { - node = NULL; - comp_name = NULL; - plist_dict_next_item(manifest_node, iter, &comp_name, &node); - if (comp_name == NULL) { - node = NULL; - break; - } - if (!strncmp(comp_name, "Timer,", 6)) { - plist_t manifest_entry = plist_copy(node); - - /* handle RestoreRequestRules */ - plist_t rules = plist_access_path(manifest_entry, 2, "Info", "RestoreRequestRules"); - if (rules) { - debug("DEBUG: Applying restore request rules for entry %s\n", comp_name); - tss_entry_apply_restore_request_rules(manifest_entry, parameters, rules); - } - - /* Make sure we have a Digest key for Trusted items even if empty */ - if (_plist_dict_get_bool(manifest_entry, "Trusted") && !plist_dict_get_item(manifest_entry, "Digest")) { - debug("DEBUG: No Digest data, using empty value for entry %s\n", comp_name); - plist_dict_set_item(manifest_entry, "Digest", plist_new_data(NULL, 0)); - } - - plist_dict_remove_item(manifest_entry, "Info"); - - /* finally add entry to request */ - plist_dict_set_item(request, comp_name, manifest_entry); - } - free(comp_name); - } - free(iter); - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -int tss_request_add_cryptex_tags(plist_t request, plist_t parameters, plist_t overrides) -{ - tss_request_add_common_tags(request, parameters, NULL); - - if (plist_dict_get_item(parameters, "Ap,LocalPolicy")) { - /* Cryptex1LocalPolicy */ - tss_request_add_local_policy_tags(request, parameters); - _plist_dict_copy_data(request, parameters, "Ap,NextStageCryptex1IM4MHash", NULL); - } else { - /* Cryptex1 */ - plist_dict_set_item(request, "@Cryptex1,Ticket", plist_new_bool(1)); - - _plist_dict_copy_bool(request, parameters, "ApSecurityMode", NULL); - _plist_dict_copy_bool(request, parameters, "ApProductionMode", NULL); - - plist_dict_iter iter = NULL; - plist_dict_new_iter(parameters, &iter); - plist_t value = NULL; - while (1) { - char *key = NULL; - plist_dict_next_item(parameters, iter, &key, &value); - if (key == NULL) - break; - if (strncmp(key, "Cryptex1", 8) == 0) { - plist_dict_set_item(request, key, plist_copy(value)); - } - free(key); - } - } - - /* apply overrides */ - if (overrides) { - plist_dict_merge(&request, overrides); - } - - return 0; -} - -static size_t tss_write_callback(char* data, size_t size, size_t nmemb, tss_response* response) -{ - size_t total = size * nmemb; - if (total != 0) { - response->content = realloc(response->content, response->length + total + 1); - memcpy(response->content + response->length, data, total); - response->content[response->length + total] = '\0'; - response->length += total; - } - - return total; -} - -plist_t tss_request_send(plist_t tss_request, const char* server_url_string) -{ - if (idevicerestore_debug) { - debug_plist(tss_request); - } - - char* request = NULL; - int status_code = -1; - int retry = 0; - int max_retries = 15; - unsigned int size = 0; - char curl_error_message[CURL_ERROR_SIZE]; - - const char* urls[6] = { - "https://gs.apple.com/TSS/controller?action=2", - "https://17.171.36.30/TSS/controller?action=2", - "https://17.151.36.30/TSS/controller?action=2", - "http://gs.apple.com/TSS/controller?action=2", - "http://17.171.36.30/TSS/controller?action=2", - "http://17.151.36.30/TSS/controller?action=2" - }; - - plist_to_xml(tss_request, &request, &size); - - tss_response* response = NULL; - memset(curl_error_message, '\0', CURL_ERROR_SIZE); - - while (retry++ < max_retries) { - response = NULL; - CURL* handle = curl_easy_init(); - if (handle == NULL) { - break; - } - struct curl_slist* header = NULL; - header = curl_slist_append(header, "Cache-Control: no-cache"); - header = curl_slist_append(header, "Content-type: text/xml; charset=\"utf-8\""); - header = curl_slist_append(header, "Expect:"); - - response = malloc(sizeof(tss_response)); - if (response == NULL) { - fprintf(stderr, "Unable to allocate sufficient memory\n"); - return NULL; - } - - response->length = 0; - response->content = malloc(1); - response->content[0] = '\0'; - - /* disable SSL verification to allow download from untrusted https locations */ - curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); - - curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&tss_write_callback); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); - curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); - curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request); - curl_easy_setopt(handle, CURLOPT_USERAGENT, USER_AGENT_STRING); - curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(request)); - if (server_url_string) { - curl_easy_setopt(handle, CURLOPT_URL, server_url_string); - info("Request URL set to %s\n", server_url_string); - } else { - int url_index = (retry - 1) % 6; - curl_easy_setopt(handle, CURLOPT_URL, urls[url_index]); - info("Request URL set to %s\n", urls[url_index]); - } - - info("Sending TSS request attempt %d... ", retry); - - curl_easy_perform(handle); - curl_slist_free_all(header); - curl_easy_cleanup(handle); - - if (strstr(response->content, "MESSAGE=SUCCESS")) { - status_code = 0; - info("response successfully received\n"); - break; - } - - if (response->length > 0) { - error("TSS server returned: %s\n", response->content); - } - - char* status = strstr(response->content, "STATUS="); - if (status) { - sscanf(status+7, "%d&%*s", &status_code); - } - if (status_code == -1) { - error("%s\n", curl_error_message); - // no status code in response. retry - free(response->content); - free(response); - response = NULL; - sleep(2); - continue; - } else if (status_code == 8) { - // server error (invalid bb request?) - break; - } else if (status_code == 49) { - // server error (invalid bb data, e.g. BbSNUM?) - break; - } else if (status_code == 69 || status_code == 94) { - // This device isn't eligible for the requested build. - break; - } else if (status_code == 100) { - // server error, most likely the request was malformed - break; - } else if (status_code == 126) { - // An internal error occured, most likely the request was malformed - break; - } else { - error("ERROR: tss_send_request: Unhandled status code %d\n", status_code); - } - } - - if (status_code != 0) { - if (response && strstr(response->content, "MESSAGE=") != NULL) { - char* message = strstr(response->content, "MESSAGE=") + strlen("MESSAGE="); - error("ERROR: TSS request failed (status=%d, message=%s)\n", status_code, message); - } else { - error("ERROR: TSS request failed: %s (status=%d)\n", curl_error_message, status_code); - } - free(request); - if (response) free(response->content); - if (response) free(response); - return NULL; - } - - char* tss_data = strstr(response->content, "<?xml"); - if (tss_data == NULL) { - error("ERROR: Incorrectly formatted TSS response\n"); - free(request); - free(response->content); - free(response); - return NULL; - } - - uint32_t tss_size = 0; - plist_t tss_response = NULL; - tss_size = response->length - (tss_data - response->content); - plist_from_xml(tss_data, tss_size, &tss_response); - free(response->content); - free(response); - - if (idevicerestore_debug) { - debug_plist(tss_response); - } - - free(request); - - return tss_response; -} - -static int 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) { - debug("DEBUG: %s: No entry '%s' in TSS response\n", __func__, name); - return -1; - } - - char *data = NULL; - uint64_t len = 0; - plist_get_data_val(node, &data, &len); - if (data) { - *length = (unsigned int)len; - *buffer = (unsigned char*)data; - return 0; - } else { - error("ERROR: Unable to get %s data from TSS response\n", name); - return -1; - } -} - -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(response, entry); - if (!entry_node || plist_get_node_type(entry_node) != PLIST_DICT) { - debug("DEBUG: %s: No entry '%s' in TSS response\n", __func__, entry); - return -1; - } - - path_node = plist_dict_get_item(entry_node, "Path"); - if (!path_node || plist_get_node_type(path_node) != PLIST_STRING) { - debug("NOTE: Unable to find %s path in TSS entry\n", entry); - return -1; - } - plist_get_string_val(path_node, &path_string); - - *path = path_string; - return 0; -} - -int tss_response_get_blob_by_path(plist_t tss, const char* path, unsigned char** blob) -{ - uint32_t i = 0; - uint32_t tss_size = 0; - uint64_t blob_size = 0; - char* entry_key = NULL; - char* blob_data = NULL; - char* entry_path = NULL; - plist_t tss_entry = NULL; - plist_t blob_node = NULL; - plist_t path_node = NULL; - plist_dict_iter iter = NULL; - - *blob = NULL; - - plist_dict_new_iter(tss, &iter); - tss_size = plist_dict_get_size(tss); - for (i = 0; i < tss_size; i++) { - plist_dict_next_item(tss, iter, &entry_key, &tss_entry); - if (entry_key == NULL) - break; - - if (!tss_entry || plist_get_node_type(tss_entry) != PLIST_DICT) { - continue; - } - - path_node = plist_dict_get_item(tss_entry, "Path"); - if (!path_node || plist_get_node_type(path_node) != PLIST_STRING) { - error("ERROR: Unable to find TSS path node in entry %s\n", entry_key); - free(iter); - return -1; - } - - plist_get_string_val(path_node, &entry_path); - if (strcmp(path, entry_path) == 0) { - blob_node = plist_dict_get_item(tss_entry, "Blob"); - if (!blob_node || plist_get_node_type(blob_node) != PLIST_DATA) { - error("ERROR: Unable to find TSS blob node in entry %s\n", entry_key); - free(iter); - return -1; - } - plist_get_data_val(blob_node, &blob_data, &blob_size); - break; - } - - free(entry_key); - } - free(iter); - - if (blob_data == NULL || blob_size <= 0) { - return -1; - } - - *blob = (unsigned char*)blob_data; - return 0; -} - -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; - plist_t tss_entry = NULL; - - *blob = NULL; - - tss_entry = plist_dict_get_item(response, entry); - if (!tss_entry || plist_get_node_type(tss_entry) != PLIST_DICT) { - debug("DEBUG: %s: No entry '%s' in TSS response\n", __func__, entry); - return -1; - } - - blob_node = plist_dict_get_item(tss_entry, "Blob"); - if (!blob_node || plist_get_node_type(blob_node) != PLIST_DATA) { - error("ERROR: Unable to find blob in %s entry\n", entry); - return -1; - } - plist_get_data_val(blob_node, &blob_data, &blob_size); - - *blob = (unsigned char*)blob_data; - return 0; -} diff --git a/src/tss.h b/src/tss.h deleted file mode 100644 index 8af2fcc..0000000 --- a/src/tss.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef IDEVICERESTORE_TSS_H -#define IDEVICERESTORE_TSS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <plist/plist.h> -#include <stdbool.h> - -/* parameters */ -int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity, bool include_manifest); - -/* request */ -plist_t tss_request_new(plist_t overrides); - -int tss_request_add_local_policy_tags(plist_t request, plist_t parameters); -int tss_request_add_common_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_ap_recovery_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t overrides, char **component_name); -int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t overrides, char **component_name); -int tss_request_add_vinyl_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_rose_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_veridian_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_timer_tags(plist_t request, plist_t parameters, plist_t overrides); -int tss_request_add_cryptex_tags(plist_t request, plist_t parameters, 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); - -/* 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 -} -#endif - -#endif |