summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Benjamin BOURGEAIS2021-05-06 17:32:09 +0200
committerGravatar Benjamin BOURGEAIS2021-05-08 14:16:50 +0200
commitb936ff28a6882c4da537473197673bb1520d8ce7 (patch)
treee6c69513f243696803cb0d7d4ee75d351db10db3
parent8355304866d2e7ead2680725c11d013712d7d19b (diff)
downloadidevicerestore-b936ff28a6882c4da537473197673bb1520d8ce7.tar.gz
idevicerestore-b936ff28a6882c4da537473197673bb1520d8ce7.tar.bz2
tss: Add new calls
- Local policy (non persistent) - recoveryOS - recoveryOS Local policy (persistent) The local policy TSS request differs slightly between the one for the restore process and the recoveryOS. The one for the restore process is meant to be used only once, and the one for the recovery os is meant to be loaded from disk, and thus has a different request. See the Ap,LocalBoot parameter.
-rw-r--r--configure.ac3
-rw-r--r--src/common.h2
-rw-r--r--src/idevicerestore.c346
-rw-r--r--src/idevicerestore.h14
-rw-r--r--src/tss.c345
-rw-r--r--src/tss.h2
6 files changed, 708 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 7df4c15..eb585c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,7 @@ PKG_CHECK_MODULES(libplist, libplist-2.0 >= $LIBPLIST_VERSION)
PKG_CHECK_MODULES(libzip, libzip >= $LIBZIP_VERSION)
PKG_CHECK_MODULES(libcurl, libcurl >= $LIBCURL_VERSION)
PKG_CHECK_MODULES(zlib, zlib)
+PKG_CHECK_MODULES(uuid, uuid)
# optional
PKG_CHECK_MODULES(openssl, openssl >= $OPENSSL_VERSION, have_openssl=yes, have_openssl=no)
@@ -51,7 +52,7 @@ AC_C_BIGENDIAN([AC_DEFINE([__BIG_ENDIAN__], [1], [big endian])],
GLOBAL_CFLAGS="-Wno-multichar -O2"
AC_LDADD=""
-AC_LDFLAGS=""
+AC_LDFLAGS="-luuid"
AC_MSG_CHECKING([whether we need platform-specific build settings])
case ${host_os} in
*mingw32*|*cygwin*)
diff --git a/src/common.h b/src/common.h
index 215d18a..5d23299 100644
--- a/src/common.h
+++ b/src/common.h
@@ -82,6 +82,8 @@ struct idevicerestore_entry_t {
struct idevicerestore_client_t {
int flags;
plist_t tss;
+ plist_t tss_localpolicy;
+ plist_t tss_recoveryos_root_ticket;
char* tss_url;
plist_t version_data;
uint64_t ecid;
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 36b86b8..2ceec6d 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -1074,10 +1074,23 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
if (client->flags & FLAG_QUIT) {
return -1;
}
+
if (get_tss_response(client, build_identity, &client->tss) < 0) {
error("ERROR: Unable to get SHSH blobs for this device\n");
return -1;
}
+ if (client->build_major >= 20) {
+ if (get_local_policy_tss_response(client, build_identity, &client->tss_localpolicy) < 0) {
+ error("ERROR: Unable to get SHSH blobs for this device (local policy)\n");
+ return -1;
+ }
+ if (get_recoveryos_root_ticket_tss_response(client, build_identity, &client->tss_recoveryos_root_ticket) <
+ 0) {
+ error("ERROR: Unable to get SHSH blobs for this device (recovery OS Root Ticket)\n");
+ return -1;
+ }
+ }
+
if (stashbag_commit_required) {
plist_t ticket = plist_dict_get_item(client->tss, "ApImg4Ticket");
if (!ticket || plist_get_node_type(ticket) != PLIST_DATA) {
@@ -1991,6 +2004,79 @@ plist_t build_manifest_get_build_identity_for_model_with_restore_behavior(plist_
return NULL;
}
+plist_t build_manifest_get_build_identity_for_model_with_restore_behavior_and_global_signing(
+ plist_t build_manifest,
+ const char *hardware_model,
+ const char *behavior,
+ uint8_t global_signing)
+{
+ plist_t build_identities_array = plist_dict_get_item(build_manifest, "BuildIdentities");
+ if (!build_identities_array || plist_get_node_type(build_identities_array) != PLIST_ARRAY) {
+ error("ERROR: Unable to find build identities node\n");
+ return NULL;
+ }
+
+ uint32_t i;
+ for (i = 0; i < plist_array_get_size(build_identities_array); i++) {
+ plist_t ident = plist_array_get_item(build_identities_array, i);
+ if (!ident || plist_get_node_type(ident) != PLIST_DICT) {
+ continue;
+ }
+ plist_t info_dict = plist_dict_get_item(ident, "Info");
+ if (!info_dict || plist_get_node_type(ident) != PLIST_DICT) {
+ continue;
+ }
+ plist_t devclass = plist_dict_get_item(info_dict, "DeviceClass");
+ if (!devclass || plist_get_node_type(devclass) != PLIST_STRING) {
+ continue;
+ }
+ char *str = NULL;
+ plist_get_string_val(devclass, &str);
+ if (strcasecmp(str, hardware_model) != 0) {
+ free(str);
+ continue;
+ }
+ free(str);
+ str = NULL;
+
+ plist_t global_signing_node = plist_dict_get_item(info_dict, "VariantSupportsGlobalSigning");
+ if (!global_signing_node) {
+ if (global_signing) {
+ continue;
+ }
+ } else {
+ uint8_t is_global_signing;
+ plist_get_bool_val(global_signing_node, &is_global_signing);
+
+ if (global_signing && !is_global_signing) {
+ continue;
+ } else if (!global_signing && is_global_signing) {
+ continue;
+ }
+ }
+
+ if (behavior) {
+ plist_t rbehavior = plist_dict_get_item(info_dict, "RestoreBehavior");
+ if (!rbehavior || plist_get_node_type(rbehavior) != PLIST_STRING) {
+ continue;
+ }
+ plist_get_string_val(rbehavior, &str);
+ if (strcasecmp(str, behavior) != 0) {
+ free(str);
+ continue;
+ } else {
+ free(str);
+ return plist_copy(ident);
+ }
+ free(str);
+ } else {
+ return plist_copy(ident);
+ }
+ }
+
+ return NULL;
+}
+
plist_t build_manifest_get_build_identity_for_model(plist_t build_manifest, const char *hardware_model)
{
return build_manifest_get_build_identity_for_model_with_restore_behavior(build_manifest, hardware_model, NULL);
@@ -2267,6 +2353,266 @@ int get_tss_response(struct idevicerestore_client_t* client, plist_t build_ident
return 0;
}
+int get_recoveryos_root_ticket_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss) {
+ plist_t request = NULL;
+ plist_t response = NULL;
+ *tss = NULL;
+
+ /* populate parameters */
+ plist_t parameters = plist_new_dict();
+
+ /* ApECID */
+ plist_dict_set_item(parameters, "ApECID", plist_new_uint(client->ecid));
+ plist_dict_set_item(parameters, "Ap,LocalBoot", plist_new_bool(0));
+
+ /* ApNonce */
+ if (client->nonce) {
+ plist_dict_set_item(parameters, "ApNonce", plist_new_data((const char*)client->nonce, client->nonce_size));
+ }
+ unsigned char* sep_nonce = NULL;
+ int sep_nonce_size = 0;
+ get_sep_nonce(client, &sep_nonce, &sep_nonce_size);
+
+ /* ApSepNonce */
+ if (sep_nonce) {
+ plist_dict_set_item(parameters, "ApSepNonce", plist_new_data((const char*)sep_nonce, sep_nonce_size));
+ free(sep_nonce);
+ }
+
+ /* ApProductionMode */
+ plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
+
+ /* ApSecurityMode */
+ if (client->image4supported) {
+ plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1));
+ }
+
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ /* create basic request */
+ /* Adds @BBTicket, @HostPlatformInfo, @VersionInfo, @UUID */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create TSS request\n");
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add common tags from manifest */
+ /* Adds Ap,OSLongVersion, AppNonce, @ApImg4Ticket */
+ if (tss_request_add_ap_img4_tags(request, parameters) < 0) {
+ error("ERROR: Unable to add AP IMG4 tags to TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add AP tags from manifest */
+ if (tss_request_add_common_tags(request, parameters, NULL) < 0) {
+ error("ERROR: Unable to add common tags to TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add AP tags from manifest */
+ /* Fills digests & co */
+ if (tss_request_add_ap_recovery_tags(request, parameters, NULL) < 0) {
+ error("ERROR: Unable to add common tags to TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* send request and grab response */
+ response = tss_request_send(request, client->tss_url);
+ if (response == NULL) {
+ info("ERROR: Unable to send TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+ // request_add_ap_tags
+
+ info("Received SHSH blobs\n");
+
+ plist_free(request);
+ plist_free(parameters);
+
+ *tss = response;
+
+ return 0;
+}
+
+int get_recovery_os_local_policy_tss_response(
+ struct idevicerestore_client_t* client,
+ plist_t build_identity,
+ plist_t* tss,
+ plist_t args) {
+ plist_t request = NULL;
+ plist_t response = NULL;
+ *tss = NULL;
+
+ /* populate parameters */
+ plist_t parameters = plist_new_dict();
+ plist_dict_set_item(parameters, "ApECID", plist_new_uint(client->ecid));
+ plist_dict_set_item(parameters, "Ap,LocalBoot", plist_new_bool(1));
+
+ plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
+ if (client->image4supported) {
+ plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1));
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(1));
+ } else {
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(0));
+ }
+
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ // Add Ap,LocalPolicy
+ uint8_t digest[SHA384_DIGEST_LENGTH];
+ SHA384(lpol_file, lpol_file_length, digest);
+ plist_t lpol = plist_new_dict();
+ plist_dict_set_item(lpol, "Digest", plist_new_data(digest, SHA384_DIGEST_LENGTH));
+ plist_dict_set_item(lpol, "Trusted", plist_new_bool(1));
+ plist_dict_set_item(parameters, "Ap,LocalPolicy", lpol);
+
+ plist_t im4m_hash = plist_dict_get_item(args, "Ap,NextStageIM4MHash");
+ plist_dict_set_item(parameters, "Ap,NextStageIM4MHash", plist_copy(im4m_hash));
+
+ plist_t nonce_hash = plist_dict_get_item(args, "Ap,RecoveryOSPolicyNonceHash");
+ plist_dict_set_item(parameters, "Ap,RecoveryOSPolicyNonceHash", plist_copy(nonce_hash));
+
+ plist_t vol_uuid_node = plist_dict_get_item(args, "Ap,VolumeUUID");
+ char* vol_uuid_str = malloc(40);
+ plist_get_string_val(vol_uuid_node, &vol_uuid_str);
+ uuid_t vol_uuid;
+ int ret = uuid_parse(vol_uuid_str, vol_uuid);
+ if (ret != 0) {
+ error("failed to parse Ap,VolumeUUID (%s) with code %d\n", vol_uuid_str, ret);
+ return -1;
+ }
+ free(vol_uuid_str);
+ plist_dict_set_item(parameters, "Ap,VolumeUUID", plist_new_data(vol_uuid, 16));
+
+ /* create basic request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create TSS request\n");
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add common tags from manifest */
+ if (tss_request_add_local_policy_tags(request, parameters) < 0) {
+ error("ERROR: Unable to add common tags to TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* send request and grab response */
+ response = tss_request_send(request, client->tss_url);
+ if (response == NULL) {
+ info("ERROR: Unable to send TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ info("Received SHSH blobs\n");
+
+ plist_free(request);
+ plist_free(parameters);
+
+ *tss = response;
+
+ return 0;
+}
+
+int get_local_policy_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss) {
+ plist_t request = NULL;
+ plist_t response = NULL;
+ *tss = NULL;
+
+ /* populate parameters */
+ plist_t parameters = plist_new_dict();
+ plist_dict_set_item(parameters, "ApECID", plist_new_uint(client->ecid));
+ plist_dict_set_item(parameters, "Ap,LocalBoot", plist_new_bool(0));
+ if (client->nonce) {
+ plist_dict_set_item(parameters, "ApNonce", plist_new_data((const char*)client->nonce, client->nonce_size));
+ }
+ unsigned char* sep_nonce = NULL;
+ int sep_nonce_size = 0;
+ get_sep_nonce(client, &sep_nonce, &sep_nonce_size);
+
+ if (sep_nonce) {
+ plist_dict_set_item(parameters, "ApSepNonce", plist_new_data((const char*)sep_nonce, sep_nonce_size));
+ free(sep_nonce);
+ }
+
+ plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
+ if (client->image4supported) {
+ plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1));
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(1));
+ } else {
+ plist_dict_set_item(parameters, "ApSupportsImg4", plist_new_bool(0));
+ }
+
+ tss_parameters_add_from_manifest(parameters, build_identity);
+
+ // Add Ap,LocalPolicy
+ uint8_t digest[SHA384_DIGEST_LENGTH];
+ SHA384(lpol_file, lpol_file_length, digest);
+ plist_t lpol = plist_new_dict();
+ plist_dict_set_item(lpol, "Digest", plist_new_data(digest, SHA384_DIGEST_LENGTH));
+ plist_dict_set_item(lpol, "Trusted", plist_new_bool(1));
+ plist_dict_set_item(parameters, "Ap,LocalPolicy", lpol);
+
+ // Add Ap,NextStageIM4MHash
+ // Get previous TSS ticket
+ uint8_t* ticket = NULL;
+ uint32_t ticket_length = 0;
+ 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);
+ plist_dict_set_item(parameters, "Ap,NextStageIM4MHash", plist_new_data(hash, SHA384_DIGEST_LENGTH));
+
+ /* create basic request */
+ request = tss_request_new(NULL);
+ if (request == NULL) {
+ error("ERROR: Unable to create TSS request\n");
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* add common tags from manifest */
+ if (tss_request_add_local_policy_tags(request, parameters) < 0) {
+ error("ERROR: Unable to add common tags to TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ /* send request and grab response */
+ response = tss_request_send(request, client->tss_url);
+ if (response == NULL) {
+ info("ERROR: Unable to send TSS request\n");
+ plist_free(request);
+ plist_free(parameters);
+ return -1;
+ }
+
+ info("Received SHSH blobs\n");
+
+ plist_free(request);
+ plist_free(parameters);
+
+ *tss = response;
+
+ return 0;
+}
+
void fixup_tss(plist_t tss)
{
plist_t node;
diff --git a/src/idevicerestore.h b/src/idevicerestore.h
index 65776c3..3d84c89 100644
--- a/src/idevicerestore.h
+++ b/src/idevicerestore.h
@@ -32,6 +32,8 @@ extern "C" {
#include <stdint.h>
#include <plist/plist.h>
#include <libirecovery.h>
+#include <openssl/sha.h>
+#include <uuid/uuid.h>
// the flag with value 1 is reserved for internal use only. don't use it.
#define FLAG_DEBUG (1 << 1)
@@ -89,12 +91,24 @@ int is_image4_supported(struct idevicerestore_client_t* client);
int get_ap_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size);
int get_sep_nonce(struct idevicerestore_client_t* client, unsigned char** nonce, int* nonce_size);
int get_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss);
+int get_local_policy_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss);
+int get_recoveryos_root_ticket_tss_response(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* tss);
+int get_recovery_os_local_policy_tss_response(
+ struct idevicerestore_client_t* client,
+ plist_t build_identity,
+ plist_t* tss,
+ plist_t args);
void fixup_tss(plist_t tss);
int build_manifest_get_identity_count(plist_t build_manifest);
int build_manifest_check_compatibility(plist_t build_manifest, const char* product);
void build_manifest_get_version_information(plist_t build_manifest, struct idevicerestore_client_t* client);
plist_t build_manifest_get_build_identity_for_model(plist_t build_manifest, const char *hardware_model);
plist_t build_manifest_get_build_identity_for_model_with_restore_behavior(plist_t build_manifest, const char *hardware_model, const char *behavior);
+plist_t build_manifest_get_build_identity_for_model_with_restore_behavior_and_global_signing(
+ plist_t build_manifest,
+ const char *hardware_model,
+ const char *behavior,
+ uint8_t global_signing);
int build_manifest_get_build_count(plist_t build_manifest);
void build_identity_print_information(plist_t build_identity);
int build_identity_check_components_in_ipsw(plist_t build_identity, const char* ipsw);
diff --git a/src/tss.c b/src/tss.c
index fecfd0f..4881343 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -35,7 +35,7 @@
#include "endianness.h"
-#define TSS_CLIENT_VERSION_STRING "libauthinstall-698.0.5"
+#define TSS_CLIENT_VERSION_STRING "libauthinstall-776.60.1"
#define ECID_STRSIZE 0x20
typedef struct {
@@ -58,7 +58,7 @@ plist_t tss_request_new(plist_t overrides) {
plist_t request = plist_new_dict();
- plist_dict_set_item(request, "@Locality", plist_new_string("en_US"));
+ plist_dict_set_item(request, "@BBTicket", plist_new_bool(1));
plist_dict_set_item(request, "@HostPlatformInfo",
#ifdef WIN32
plist_new_string("windows")
@@ -82,6 +82,116 @@ plist_t tss_request_new(plist_t overrides) {
return request;
}
+int tss_request_add_local_policy_tags(plist_t request, plist_t parameters)
+{
+ plist_t node = NULL;
+
+ plist_dict_set_item(request, "@ApImg4Ticket", plist_new_bool(1));
+
+ /* Ap,LocalBoot */
+ node = plist_dict_get_item(parameters, "Ap,LocalBoot");
+ if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) {
+ error("ERROR: Unable to find required Ap,LocalBoot in parameters\n");
+ return -1;
+ }
+ plist_dict_set_item(request, "Ap,LocalBoot", plist_copy(node));
+ node = NULL;
+
+ /* Ap,LocalPolicy */
+ node = plist_dict_get_item(parameters, "Ap,LocalPolicy");
+ if (!node || plist_get_node_type(node) != PLIST_DICT) {
+ error("ERROR: Unable to find required Ap,LocalPolicy in parameters\n");
+ return -1;
+ }
+ plist_dict_set_item(request, "Ap,LocalPolicy", plist_copy(node));
+ node = NULL;
+
+ /* Ap,NextStageIM4MHash */
+ node = plist_dict_get_item(parameters, "Ap,NextStageIM4MHash");
+ if (!node || plist_get_node_type(node) != PLIST_DATA) {
+ error("ERROR: Unable to find required Ap,NextStageIM4MHash in parameters\n");
+ return -1;
+ }
+ plist_dict_set_item(request, "Ap,NextStageIM4MHash", plist_copy(node));
+ node = NULL;
+
+ /* Ap,RecoveryOSPolicyNonceHash */
+ node = plist_dict_get_item(parameters, "Ap,RecoveryOSPolicyNonceHash");
+ if (node) {
+ plist_dict_set_item(request, "Ap,RecoveryOSPolicyNonceHash", plist_copy(node));
+ }
+ node = NULL;
+
+ /* Ap,VolumeUUID */
+ node = plist_dict_get_item(parameters, "Ap,VolumeUUID");
+ if (node) {
+ plist_dict_set_item(request, "Ap,VolumeUUID", plist_copy(node));
+ }
+ node = NULL;
+
+ /* ApECID */
+ node = plist_dict_get_item(parameters, "ApECID");
+ if (node) {
+ plist_dict_set_item(request, "ApECID", plist_copy(node));
+ }
+ node = NULL;
+
+ /* ApChipID */
+ node = plist_dict_get_item(parameters, "ApChipID");
+ if (node) {
+ plist_dict_set_item(request, "ApChipID", plist_copy(node));
+ }
+ node = NULL;
+
+ /* ApBoardID */
+ node = plist_dict_get_item(parameters, "ApBoardID");
+ if (node) {
+ plist_dict_set_item(request, "ApBoardID", plist_copy(node));
+ }
+ node = NULL;
+
+ /* ApSecurityDomain */
+ node = plist_dict_get_item(parameters, "ApSecurityDomain");
+ if (node) {
+ plist_dict_set_item(request, "ApSecurityDomain", plist_copy(node));
+ }
+ node = NULL;
+
+ /* ApNonce */
+ node = plist_dict_get_item(parameters, "ApNonce");
+ if (node) {
+ plist_dict_set_item(request, "ApNonce", plist_copy(node));
+ }
+ node = NULL;
+
+ /* ApSecurityMode */
+ node = plist_dict_get_item(request, "ApSecurityMode");
+ if (!node) {
+ /* copy from parameters if available */
+ node = plist_dict_get_item(parameters, "ApSecurityMode");
+ if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) {
+ error("ERROR: Unable to find required ApSecurityMode in parameters\n");
+ return -1;
+ }
+ plist_dict_set_item(request, "ApSecurityMode", plist_copy(node));
+ node = NULL;
+ }
+
+ node = plist_dict_get_item(request, "ApProductionMode");
+ if (!node) {
+ /* ApProductionMode */
+ node = plist_dict_get_item(parameters, "ApProductionMode");
+ if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) {
+ error("ERROR: Unable to find required ApProductionMode in parameters\n");
+ return -1;
+ }
+ plist_dict_set_item(request, "ApProductionMode", plist_copy(node));
+ node = NULL;
+ }
+
+ return 0;
+}
+
int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity)
{
plist_t node = NULL;
@@ -96,6 +206,12 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity)
plist_dict_set_item(parameters, "UniqueBuildID", plist_copy(node));
node = NULL;
+ /* Ap,OSLongVersion */
+ node = plist_dict_get_item(build_identity, "Ap,OSLongVersion");
+ if (node) {
+ plist_dict_set_item(parameters, "Ap,OSLongVersion", plist_copy(node));
+ }
+
/* ApChipID */
int chip_id = 0;
node = plist_dict_get_item(build_identity, "ApChipID");
@@ -359,6 +475,12 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) {
return -1;
}
+ /* Ap,OSLongVersion */
+ node = plist_dict_get_item(parameters, "Ap,OSLongVersion");
+ if (node) {
+ plist_dict_set_item(request, "Ap,OSLongVersion", plist_copy(node));
+ }
+
/* ApNonce */
node = plist_dict_get_item(parameters, "ApNonce");
if (!node || plist_get_node_type(node) != PLIST_DATA) {
@@ -594,7 +716,7 @@ static void tss_entry_apply_restore_request_rules(plist_t tss_entry, plist_t par
}
}
-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) {
/* 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) {
@@ -622,6 +744,120 @@ int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrid
continue;
}
+ // Compared to ac2, not needed for RecoveryOSRootTicket
+ if ((strcmp(key, "SE,UpdatePayload") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "BaseSystem") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "ANS") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,AudioBootChime") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,CIO") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,RestoreCIO") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,RestoreTMU") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,TMU") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,rOSLogo1") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "Ap,rOSLogo2") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "AppleLogo") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "DCP") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "LLB") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RecoveryMode") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreANS") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreDCP") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreDeviceTree") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreKernelCache") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreLogo") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreRamDisk") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "RestoreSEP") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "SEP") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "ftap") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "ftsp") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "iBEC") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "iBSS") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "rfta") == 0)) {
+ free(key);
+ continue;
+ }
+ if ((strcmp(key, "rfts") == 0)) {
+ free(key);
+ continue;
+ }
+
/* FIXME: only used with diagnostics firmware */
if (strcmp(key, "Diags") == 0) {
free(key);
@@ -629,11 +865,114 @@ int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrid
}
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", __func__, key);
+ continue;
+ }
+
plist_t info_dict = plist_dict_get_item(manifest_entry, "Info");
+ if (!_plist_dict_get_bool(info_dict, "IsFirmwarePayload") && !_plist_dict_get_bool(info_dict, "IsSecondaryFirmwarePayload") && !_plist_dict_get_bool(info_dict, "IsFUDFirmware")) {
+ debug("DEBUG: %s: Skipping '%s' as it is neither firmware nor secondary nor FUD firmware payload\n", __func__, key);
+ continue;
+ }
+ }
+
+ /* copy this entry */
+ plist_t tss_entry = plist_copy(manifest_entry);
+
+ // ac2 TSS recoveryOSRootTicket needs EPRO and ESEC to be true
+ plist_dict_set_item(tss_entry, "EPRO", plist_new_bool(1));
+ plist_dict_set_item(tss_entry, "ESEC", plist_new_bool(1));
+
+ /* 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 */
+ plist_t node = plist_dict_get_item(manifest_entry, "Trusted");
+ if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
+ uint8_t trusted;
+ plist_get_bool_val(node, &trusted);
+ if (trusted && !plist_access_path(manifest_entry, 1, "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) {
+ 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");
+ return -1;
+ }
+
+ /* do not populate BaseBandFirmware, only in basebaseband request */
+ if ((strcmp(key, "BasebandFirmware") == 0)) {
+ free(key);
+ continue;
+ }
+
+ // Compared to ac2, not needed
+ if ((strcmp(key, "SE,UpdatePayload") == 0)) {
+ free(key);
+ continue;
+ }
+
+ // Compared to ac2, not needed
+ if ((strcmp(key, "BaseSystem") == 0)) {
+ free(key);
+ continue;
+ }
+
+ /* FIXME: only used with diagnostics firmware */
+ if (strcmp(key, "Diags") == 0) {
+ free(key);
+ 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", __func__, key);
continue;
}
+
+ plist_t info_dict = plist_dict_get_item(manifest_entry, "Info");
if (!_plist_dict_get_bool(info_dict, "IsFirmwarePayload") && !_plist_dict_get_bool(info_dict, "IsSecondaryFirmwarePayload") && !_plist_dict_get_bool(info_dict, "IsFUDFirmware")) {
debug("DEBUG: %s: Skipping '%s' as it is neither firmware nor secondary nor FUD firmware payload\n", __func__, key);
continue;
diff --git a/src/tss.h b/src/tss.h
index 85ade57..86dce42 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -36,8 +36,10 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity)
/* 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);