From ea4d7b1d79d5305ac85c84b769e77b2c632b0025 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 23 Apr 2022 21:30:41 -0400 Subject: [PATCH] 0.336.0 Release Merge all changes from the development branch. --- README.md | 86 +++++++------ tsschecker/Makefile.am | 4 - tsschecker/main.c | 30 +++-- tsschecker/tss.c | 268 ++++++++++++++++++++++++++++++---------- tsschecker/tss.h | 3 + tsschecker/tsschecker.c | 37 ++++-- tsschecker/tsschecker.h | 1 + 7 files changed, 300 insertions(+), 129 deletions(-) diff --git a/README.md b/README.md index 1dbe0235..f94fccfd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # tsschecker -tsschecker is a powerful tool to check TSS signing status on combinations of various apple devices and firmware versions. +A Powerful tool to check TSS signing status on combinations of various apple devices and firmware versions. ## Features * Supports: Apple TV, Apple Watch, HomePod, iPad, iPhone, iPod touch, M1 Macs and the T2 Coprocessor. @@ -10,17 +10,25 @@ tsschecker is a powerful tool to check TSS signing status on combinations of var tsschecker is not only meant to be used to check firmware signing status, but also to explore Apple's TSS servers.
By using all of its customization possibilities, you might discover a combination of devices and firmware versions that is getting signed but wasn't getting signed before. -# About nonces: -## recommended generators for saving tickets: -* `0xbd34a880be0b53f3` // default on the Electra, Chimera and Odyssey jailbreak apps. -* `0x1111111111111111` // default on the unc0ver jailbreak app. +# About Nonces: +A [Nonce](https://wikipedia.org/wiki/Cryptographic_nonce) ("Number-used-ONCE") is a randomly generated value that is used to randomize apple's signed hash blobs. -## Nonce Entangling (Apple A12/S4 and newer) -Newer devices, such as the iPhone XR or the Apple Watch Series 4 (and any device newer) have nonce-entangling. +it is created by the device with a nonce seed (generator) and then hashes that seed to create the nonce.
On arm64e devices the nonce is also encrypted with the device's UID Key, see "Nonce Entangling" for more details. -this means any boot nonce generated by your device is now also UID derived, and consequently device-specific.
to save usable tickets for a newer device, you need to get the boot nonce that your device actually generates from your generator. +## Recommended nonce-seeds (Generators) for saving tickets: +* `0xbd34a880be0b53f3` // default on the [Electra](https://coolstar.org/electra/), [Chimera](https://chimera.coolstar.org/) and [Odyssey](https://theodyssey.dev/) jailbreak apps. +* `0x1111111111111111` // default on the [unc0ver](https://unc0ver.dev) jailbreak app. -for information on how to get your actual boot nonce, [see this post on r/jailbreak](https://www.reddit.com/r/jailbreak/comments/cssh8f/tutorial_easiest_way_to_save_blobs_on_a12/). +## Nonce Entangling (arm64e devices) +arm64e devices such as the iPhone XR, Apple Watch Series 4 and all newer devices have nonce-entangling. + +Nonce Entangling works by further randomizing the boot nonce by encrypting it with the device's [unique ID key](https://www.theiphonewiki.com/wiki/UID_key),
+making the nonce created from the generator specific to that device only. + +To save tickets for an arm64e device, you must get the boot nonce that the device creates from your generator,
+the simpliest way to get a nonce/generator pair is to use airsquared's [blobsaver](https://github.com/airsquared/blobsaver) tool and read them from the device. + +if you need more information, [see this post on r/jailbreak](https://www.reddit.com/r/jailbreak/comments/cssh8f/tutorial_easiest_way_to_save_blobs_on_a12/). ## Nonce Collisions: @@ -66,37 +74,39 @@ To compile, run: ```bash ./autogen.sh make -sudo make install +make install ``` # Help Usage: `tsschecker [OPTIONS]` -Example: `tsschecker -d iPhone10,1 -B D20AP -e [ECID] -i 13.4.1 --generator 0x1111111111111111 -s` - -| option (short) | option (long) | description | -|----------------|---------------------------|-----------------------------------------------------------------------------------| -| `-h` | `--help` | prints usage information | -| `-d` | `--device MODEL` | specify device by its model (eg. `iPhone8,1`) | -| `-i` | `--ios VERSION` | specify firmware version (eg. `13.4.1`) | -| `-Z` | `--buildid BUILD ` | specific buildid instead of firmware version (eg. `17E255`) | -| `-B` | `--boardconfig BOARD ` | specific boardconfig instead of device model (eg. `n71ap`) | -| `-o` | `--ota` | check OTA signing status, instead of normal restore | -| `-b` | `--no-baseband` | don't check baseband signing status. Request tickets without baseband | -| `-m` | `--build-manifest` | manually specify a BuildManifest (can be used with `-d`) | -| `-s` | `--save` | save fetched shsh blobs (mostly makes sense with -e) | -| `-u` | `--update-install `| request update tickets instead of erase | -| `-l` | `--latest` | use the latest public firmware version instead of manually specifying one
especially useful with `-s` and `-e` for saving signing tickets | -| `-e` | `--ecid ECID` | manually specify ECID to be used for fetching blobs, instead of using random ones.
ECID must be either DEC or HEX eg. `5482657301265` or `ab46efcbf71` | -| `-g` | `--generator GEN` | manually specify generator in format 0x%%16llx | -| | `--apnonce NONCE` | manually specify ApNonce instead of using random ones
(required for saving blobs for A12/S4 and newer devices with generator) | -| | `--sepnonce NONCE` | manually specify SepNonce instead of using random ones (not required for saving signing tickets) | -| | `--bbsnum SNUM` | manually specify BbSNUM in HEX to save valid BBTickets (not required for saving blobs) | -| | `--save-path PATH` | specify path for saving shsh blobs | -| |`--beta` | request ticket for a beta instead of normal release (use with `-o`) | -| |`--list-devices` | list all known devices | -| |`--list-ios` | list all known firmware versions | -| |`--nocache` | ignore caches and re-download required files | -| |`--print-tss-request` | print the TSS request that will be sent to Apple | -| |`--print-tss-response` | print the TSS response that comes from Apple | -| |`--raw` | send raw file to Apple's TSS server (useful for debugging) | +Example: `tsschecker -d iPhone10,3 -B D22AP -e 5482657301265 -i 15.4.1 --generator 0x1111111111111111 -s` + +| option (short) | option (long) | description | +| ------------------ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `-h` | `--help` | prints usage information | +| `-d` | `--device MODEL` | specify device by its model (eg. iPhone10,3) | +| `-i` | `--ios VERSION` | specify firmware version (eg. 15.4.1) | +| `-Z` | `--buildid BUILD ` | specify buildid instead of firmware version (eg. 19E258) | +| `-B` | `--boardconfig BOARD ` | specify boardconfig instead of device model (eg. d22ap) | +| `-o` | `--ota` | check OTA signing status, instead of normal restore | +| `-b` | `--no-baseband` | don't check baseband signing status. Request tickets without baseband | +| `-m` | `--build-manifest` | manually specify a BuildManifest (can be used with -d) | +| `-s` | `--save` | save fetched shsh blobs (mostly makes sense with -e) | +| `-u` | `--update-install` | request update tickets instead of erase | +| `-l` | `--latest` | use the latest public firmware version instead of manually specifying one
especially useful with -s and -e for saving shsh blobs | +| `-e` | `--ecid ECID` | manually specify ECID to be used for fetching blobs, instead of using random ones
ECID must be either DEC or HEX eg. 5482657301265 or 0xab46efcbf71 | +| `-g` | `--generator GEN` | manually specify generator in HEX format 16 in length (eg. 0x1111111111111111) | +| | `--apnonce NONCE` | manually specify ApNonce instead of using random ones
(required when saving blobs for arm64e devices with matching generator) | +| | `--sepnonce NONCE` | manually specify SEP Nonce instead of using random ones (not required for saving blobs) | +| | `--bbsnum SNUM` | manually specify BbSNUM in HEX to save valid BBTickets (not required for saving blobs) | +| | `--save-path PATH` | specify output path for saving shsh blobs | +| | `--server-url URL` | manually specify TSS server URL | +| | `--bplist` | save fetched blobs in a binary plist (.bshsh2 format) | +| | `--beta` | request tickets for a beta instead of normal release (use with -o) | +| | `--list-devices` | list known devices from firmwares.json | +| | `--list-versions` | list all known firmware versions for the specified device | +| | `--nocache` | ignore caches and re-download required files | +| | `--print-tss-request` | print the TSS request that will be sent to Apple | +| | `--print-tss-response` | print the TSS response that comes from Apple | +| | `--raw` | send raw file to Apple's TSS server (useful for debugging) | diff --git a/tsschecker/Makefile.am b/tsschecker/Makefile.am index 2ad74291..fcc7ecdb 100644 --- a/tsschecker/Makefile.am +++ b/tsschecker/Makefile.am @@ -18,8 +18,4 @@ tsschecker_LDADD = $(AM_LDFLAGS) libjssy.a tsschecker_SOURCES = tsschecker.c tss.c download.c main.c endif -if WINDOWS -tsschecker_LDFLAGS = -lpthread -Wl,--allow-multiple-definition $(AM_LDFLAGS) -else tsschecker_LDFLAGS = $(AM_LDFLAGS) -endif diff --git a/tsschecker/main.c b/tsschecker/main.c index a28fc8bd..75d2160f 100644 --- a/tsschecker/main.c +++ b/tsschecker/main.c @@ -25,7 +25,7 @@ #include "tsschecker.h" #include "all.h" -#define FLAG_LIST_IOS (1 << 0) +#define FLAG_LIST_VERSIONS (1 << 0) #define FLAG_LIST_DEVICES (1 << 1) #define FLAG_BUILDMANIFEST (1 << 2) #define FLAG_LATEST_IOS (1 << 3) @@ -48,7 +48,7 @@ static struct option longopts[] = { { "buildid", required_argument, NULL, 'Z' }, { "debug", no_argument, NULL, 0 }, { "list-devices", no_argument, NULL, 1 }, - { "list-ios", no_argument, NULL, 2 }, + { "list-versions", no_argument, NULL, 2 }, { "save-path", required_argument, NULL, 3 }, { "print-tss-request", no_argument, NULL, 4 }, { "print-tss-response", no_argument, NULL, 5 }, @@ -59,6 +59,7 @@ static struct option longopts[] = { { "raw", required_argument, NULL, 10 }, { "bbsnum", required_argument, NULL, 11 }, { "server-url", required_argument, NULL, 12 }, + { "bplist", no_argument, NULL, 13 }, { "generator", required_argument, NULL, 'g' }, { NULL, 0, NULL, 0 } }; @@ -68,8 +69,8 @@ void cmd_help(){ printf("Usage: tsschecker [OPTIONS]\n\n"); printf(" -h, --help\t\t\tprints usage information\n"); printf(" -d, --device MODEL\t\tspecify device by its model (eg. iPhone10,3)\n"); - printf(" -i, --ios VERSION\t\tspecify firmware version (eg. 14.7.1)\n"); - printf(" -Z --buildid BUILD\t\tspecify buildid instead of firmware version (eg. 18G82)\n"); + printf(" -i, --ios VERSION\t\tspecify firmware version (eg. 15.4.1)\n"); + printf(" -Z --buildid BUILD\t\tspecify buildid instead of firmware version (eg. 19E258)\n"); printf(" -B, --boardconfig BOARD \tspecify boardconfig instead of device model (eg. d22ap)\n"); printf(" -o, --ota\t\t\tcheck OTA signing status, instead of normal restore\n"); printf(" -b, --no-baseband\t\tdon't check baseband signing status. Request tickets without baseband\n"); @@ -81,14 +82,15 @@ void cmd_help(){ printf(" -e, --ecid ECID\t\tmanually specify ECID to be used for fetching blobs, instead of using random ones\n"); printf(" \t\tECID must be either DEC or HEX eg. 5482657301265 or 0xab46efcbf71\n"); printf(" -g, --generator GEN\t\tmanually specify generator in HEX format 16 in length (eg. 0x1111111111111111)\n\n"); - printf(" --apnonce NONCE\t\tmanually specify ApNonce instead of using random ones\n\t\t\t\t(required for saving blobs for A12/S4 and newer devices with generator)\n\n"); + printf(" --apnonce NONCE\t\tmanually specify ApNonce instead of using random ones\n\t\t\t\t(required when saving blobs for arm64e devices with matching generator)\n\n"); printf(" --sepnonce NONCE\t\tmanually specify SEP Nonce instead of using random ones (not required for saving blobs)\n"); printf(" --bbsnum SNUM\t\tmanually specify BbSNUM in HEX to save valid BBTickets (not required for saving blobs)\n\n"); printf(" --save-path PATH\t\tspecify output path for saving shsh blobs\n"); printf(" --server-url URL\t\tmanually specify TSS server URL\n"); + printf(" --bplist\t\t\tsave fetched blobs in a binary plist (.bshsh2 format)\n"); printf(" --beta\t\t\trequest tickets for a beta instead of normal release (use with -o)\n"); - printf(" --list-devices\t\tlist all known devices\n"); - printf(" --list-ios\t\tlist all known firmware versions\n"); + printf(" --list-devices\t\tlist known devices from firmwares.json\n"); + printf(" --list-versions\t\tlist all known firmware versions for the specified device\n"); printf(" --nocache \t\tignore caches and re-download required files\n"); printf(" --print-tss-request\tprint the TSS request that will be sent to Apple\n"); printf(" --print-tss-response\tprint the TSS response that comes from Apple\n"); @@ -157,6 +159,7 @@ int main(int argc, const char * argv[]) { dbglog = 1; idevicerestore_debug = 0; save_shshblobs = 0; + save_bplist = 0; int optindex = 0; int opt = 0; long flags = 0; @@ -250,8 +253,8 @@ int main(int argc, const char * argv[]) { case 1: // only long option: "list-devices" flags |= FLAG_LIST_DEVICES; break; - case 2: // only long option: "list-ios" - flags |= FLAG_LIST_IOS; + case 2: // only long option: "list-versions" + flags |= FLAG_LIST_VERSIONS; break; case 3: // only long option: "save-path" shshSavePath = optarg; @@ -284,6 +287,9 @@ int main(int argc, const char * argv[]) { case 12: // only long option: "server-url" serverUrl = optarg; break; + case 13: // only long option: "bplist" + save_bplist = 1; + break; default: cmd_help(); return -1; @@ -416,14 +422,14 @@ int main(int argc, const char * argv[]) { free((char*)versVals.version); if (--versionCnt == 0) reterror(-9, "[TSSC] automatic firmware selection couldn't find non-beta firmware\n"); } - info("[TSSC] selecting latest version of firmware: %s\n",versVals.version); + info("[TSSC] selecting latest version: %s\n",versVals.version); if (bpos) *bpos= '\0'; if (versions) free(versions[versionCnt-1]),free(versions); } if (flags & FLAG_LIST_DEVICES) { printListOfDevices(firmwareTokens); - }else if (flags & FLAG_LIST_IOS){ + }else if (flags & FLAG_LIST_VERSIONS){ if (!devVals.deviceModel) reterror(-3,"[TSSC] please specify a device for this option\n\tuse -h for more help\n"); @@ -440,7 +446,7 @@ int main(int argc, const char * argv[]) { isSigned = isVersionSignedForDevice(firmwareTokens, &versVals, &devVals, serverUrl); } - if (isSigned >=0) printf("\n%s %s for device %s %s being signed!\n",(versVals.buildID) ? "Build" : "iOS" ,(versVals.buildID ? versVals.buildID : versVals.version),devVals.deviceModel, (isSigned) ? "IS" : "IS NOT"); + if (isSigned >=0) printf("\n%s %s for device %s %s being signed!\n",(versVals.buildID) ? "Build" : "Firmware version" ,(versVals.buildID ? versVals.buildID : versVals.version),devVals.deviceModel, (isSigned) ? "IS" : "is NOT"); else{ putchar('\n'); reterror(-69, "[TSSC] checking tss status failed!\n"); diff --git a/tsschecker/tss.c b/tsschecker/tss.c index 8a2ec3cc..9777ba50 100644 --- a/tsschecker/tss.c +++ b/tsschecker/tss.c @@ -48,7 +48,7 @@ #include "tss.h" #include "endianness.h" -#define AUTH_VERSION "850.0.2" +#define AUTH_VERSION "851.102.1.100.4" #ifdef WIN32 #define TSS_CLIENT_VERSION_STRING "libauthinstall_Win-"AUTH_VERSION"" @@ -59,8 +59,6 @@ #define ECID_STRSIZE 0x20 #define GET_RAND(min, max) ((rand() % (max - min)) + min) -#define tsserror(a ...) if (idevicerestore_debug) printf(a) - typedef struct { int length; char* content; @@ -104,7 +102,7 @@ char* ecid_to_string(uint64_t ecid) { char* ecid_string = malloc(ECID_STRSIZE); memset(ecid_string, '\0', ECID_STRSIZE); if (ecid == 0) { - tsserror("ERROR: Invalid ECID passed.\n"); + error("ERROR: Invalid ECID passed.\n"); return NULL; } snprintf(ecid_string, ECID_STRSIZE, FMT_qu, (long long unsigned int)ecid); @@ -236,7 +234,7 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) /* UniqueBuildID */ node = plist_dict_get_item(build_identity, "UniqueBuildID"); if (!node || plist_get_node_type(node) != PLIST_DATA) { - tsserror("ERROR: Unable to find UniqueBuildID node\n"); + error("ERROR: Unable to find UniqueBuildID node\n"); return -1; } @@ -247,7 +245,7 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) int chip_id = 0; node = plist_dict_get_item(build_identity, "ApChipID"); if (!node || plist_get_node_type(node) != PLIST_STRING) { - tsserror("ERROR: Unable to find ApChipID node\n"); + error("ERROR: Unable to find ApChipID node\n"); return -1; } plist_get_string_val(node, &string); @@ -261,7 +259,7 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) int board_id = 0; node = plist_dict_get_item(build_identity, "ApBoardID"); if (!node || plist_get_node_type(node) != PLIST_STRING) { - tsserror("ERROR: Unable to find ApBoardID node\n"); + error("ERROR: Unable to find ApBoardID node\n"); return -1; } plist_get_string_val(node, &string); @@ -275,7 +273,7 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) int security_domain = 0; node = plist_dict_get_item(build_identity, "ApSecurityDomain"); if (!node || plist_get_node_type(node) != PLIST_STRING) { - tsserror("ERROR: Unable to find ApSecurityDomain node\n"); + error("ERROR: Unable to find ApSecurityDomain node\n"); return -1; } plist_get_string_val(node, &string); @@ -504,10 +502,52 @@ int tss_parameters_add_from_manifest(plist_t parameters, plist_t build_identity) } node = NULL; + /* add Timer,BoardID,1 */ + node = plist_dict_get_item(build_identity, "Timer,BoardID,1"); + if (node) { + plist_dict_set_item(parameters, "Timer,BoardID,1", plist_copy(node)); + } + node = NULL; + + /* add Timer,BoardID,2 */ + node = plist_dict_get_item(build_identity, "Timer,BoardID,2"); + if (node) { + plist_dict_set_item(parameters, "Timer,BoardID,2", plist_copy(node)); + } + node = NULL; + + /* add Timer,ChipID,1 */ + node = plist_dict_get_item(build_identity, "Timer,ChipID,1"); + if (node) { + plist_dict_set_item(parameters, "Timer,ChipID,1", plist_copy(node)); + } + node = NULL; + + /* add Timer,ChipID,2 */ + node = plist_dict_get_item(build_identity, "Timer,ChipID,2"); + if (node) { + plist_dict_set_item(parameters, "Timer,ChipID,2", plist_copy(node)); + } + node = NULL; + + /* add Timer,SecurityDomain,1 */ + node = plist_dict_get_item(build_identity, "Timer,SecurityDomain,1"); + if (node) { + plist_dict_set_item(parameters, "Timer,SecurityDomain,1", plist_copy(node)); + } + node = NULL; + + /* add Timer,SecurityDomain,2 */ + node = plist_dict_get_item(build_identity, "Timer,SecurityDomain,2"); + if (node) { + plist_dict_set_item(parameters, "Timer,SecurityDomain,2", plist_copy(node)); + } + node = NULL; + /* add build identity manifest dictionary */ node = plist_dict_get_item(build_identity, "Manifest"); if (!node || plist_get_node_type(node) != PLIST_DICT) { - tsserror("ERROR: Unable to find Manifest node\n"); + error("ERROR: Unable to find Manifest node\n"); return -1; } plist_dict_set_item(parameters, "Manifest", plist_copy(node)); @@ -519,7 +559,7 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) { plist_t node = NULL; if (!parameters) { - tsserror("ERROR: Missing required AP parameters\n"); + error("ERROR: Missing required AP parameters\n"); return -1; } @@ -527,7 +567,7 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) { node = plist_dict_get_item(parameters, "ApNonce"); if (node) { if (plist_get_node_type(node) != PLIST_DATA) { - tsserror("ERROR: Unable to find required ApNonce in parameters\n"); + error("ERROR: Unable to find required ApNonce in parameters\n"); return -1; } plist_dict_set_item(request, "ApNonce", plist_copy(node)); @@ -543,7 +583,7 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) { /* copy from parameters if available */ node = plist_dict_get_item(parameters, "ApSecurityMode"); if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) { - tsserror("ERROR: Unable to find required ApSecurityMode in parameters\n"); + error("ERROR: Unable to find required ApSecurityMode in parameters\n"); return -1; } plist_dict_set_item(request, "ApSecurityMode", plist_copy(node)); @@ -555,7 +595,7 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) { /* ApProductionMode */ node = plist_dict_get_item(parameters, "ApProductionMode"); if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) { - tsserror("ERROR: Unable to find required ApProductionMode in parameters\n"); + error("ERROR: Unable to find required ApProductionMode in parameters\n"); return -1; } plist_dict_set_item(request, "ApProductionMode", plist_copy(node)); @@ -565,7 +605,7 @@ int tss_request_add_ap_img4_tags(plist_t request, plist_t parameters) { /* ApSepNonce */ node = plist_dict_get_item(parameters, "ApSepNonce"); if (!node || plist_get_node_type(node) != PLIST_DATA) { - tsserror("ERROR: Unable to find required ApSepNonce in parameters\n"); + error("ERROR: Unable to find required ApSepNonce in parameters\n"); return -1; } plist_dict_set_item(request, "SepNonce", plist_copy(node)); @@ -584,7 +624,7 @@ int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) { plist_t node = NULL; if (!parameters) { - tsserror("ERROR: Missing required AP parameters\n"); + error("ERROR: Missing required AP parameters\n"); return -1; } @@ -592,7 +632,7 @@ int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) { node = plist_dict_get_item(parameters, "ApNonce"); if (node) { if (plist_get_node_type(node) != PLIST_DATA) { - tsserror("ERROR: Unable to find required ApNonce in parameters\n"); + error("ERROR: Unable to find required ApNonce in parameters\n"); return -1; } plist_dict_set_item(request, "ApNonce", plist_copy(node)); @@ -605,7 +645,7 @@ int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) { /* ApBoardID */ node = plist_dict_get_item(request, "ApBoardID"); if (!node || plist_get_node_type(node) != PLIST_UINT) { - tsserror("ERROR: Unable to find required ApBoardID in request\n"); + error("ERROR: Unable to find required ApBoardID in request\n"); return -1; } node = NULL; @@ -613,7 +653,7 @@ int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) { /* ApChipID */ node = plist_dict_get_item(request, "ApChipID"); if (!node || plist_get_node_type(node) != PLIST_UINT) { - tsserror("ERROR: Unable to find required ApChipID in request\n"); + error("ERROR: Unable to find required ApChipID in request\n"); return -1; } node = NULL; @@ -621,7 +661,7 @@ int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) { /* ApSecurityDomain */ node = plist_dict_get_item(request, "ApSecurityDomain"); if (!node || plist_get_node_type(node) != PLIST_UINT) { - tsserror("ERROR: Unable to find required ApSecurityDomain in request\n"); + error("ERROR: Unable to find required ApSecurityDomain in request\n"); return -1; } node = NULL; @@ -629,7 +669,7 @@ int tss_request_add_ap_img3_tags(plist_t request, plist_t parameters) { /* ApProductionMode */ node = plist_dict_get_item(parameters, "ApProductionMode"); if (!node || plist_get_node_type(node) != PLIST_BOOLEAN) { - tsserror("ERROR: Unable to find required ApProductionMode in parameters\n"); + error("ERROR: Unable to find required ApProductionMode in parameters\n"); return -1; } plist_dict_set_item(request, "ApProductionMode", plist_copy(node)); @@ -723,7 +763,7 @@ static void tss_entry_apply_restore_request_rules(plist_t tss_entry, plist_t par } else if (!strcmp(key, "ApInRomDFU")) { value2 = plist_dict_get_item(parameters, "ApInRomDFU"); } else { - tsserror("WARNING: Unhandled condition '%s' while parsing RestoreRequestRules\n", key); + error("WARNING: Unhandled condition '%s' while parsing RestoreRequestRules\n", key); value2 = NULL; } if (value2) { @@ -765,7 +805,7 @@ int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrid /* 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) { - tsserror("ERROR: Unable to find restore manifest\n"); + error("ERROR: Unable to find restore manifest\n"); return -1; } @@ -779,7 +819,7 @@ int tss_request_add_ap_tags(plist_t request, plist_t parameters, plist_t overrid if (key == NULL) break; if (!manifest_entry || plist_get_node_type(manifest_entry) != PLIST_DICT) { - tsserror("ERROR: Unable to fetch BuildManifest entry\n"); + error("ERROR: Unable to fetch BuildManifest entry\n"); return -1; } @@ -917,7 +957,7 @@ int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t o /* BbGoldCertId */ node = plist_dict_get_item(parameters, "BbGoldCertId"); if (!node || plist_get_node_type(node) != PLIST_UINT) { - tsserror("ERROR: Unable to find required BbGoldCertId in parameters\n"); + error("ERROR: Unable to find required BbGoldCertId in parameters\n"); return -1; } node = plist_copy(node); @@ -931,7 +971,7 @@ int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t o /* BbSNUM */ node = plist_dict_get_item(parameters, "BbSNUM"); if (!node || plist_get_node_type(node) != PLIST_DATA) { - tsserror("ERROR: Unable to find required BbSNUM in parameters\n"); + error("ERROR: Unable to find required BbSNUM in parameters\n"); return -1; } plist_dict_set_item(request, "BbSNUM", plist_copy(node)); @@ -940,7 +980,7 @@ int tss_request_add_baseband_tags(plist_t request, plist_t parameters, plist_t o /* BasebandFirmware */ node = plist_access_path(parameters, 2, "Manifest", "BasebandFirmware"); if (!node || plist_get_node_type(node) != PLIST_DICT) { - tsserror("ERROR: Unable to get BasebandFirmware node\n"); + error("ERROR: Unable to get BasebandFirmware node\n"); return -1; } plist_t bbfwdict = plist_copy(node); @@ -976,7 +1016,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); return -1; } @@ -987,7 +1027,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid /* add SE,ChipID */ node = plist_dict_get_item(parameters, "SE,ChipID"); if (!node) { - tsserror("ERROR: %s: Unable to find required SE,ChipID in parameters\n", __func__); + error("ERROR: %s: Unable to find required SE,ChipID in parameters\n", __func__); return -1; } plist_dict_set_item(request, "SE,ChipID", plist_copy(node)); @@ -996,7 +1036,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid /* add SE,ID */ node = plist_dict_get_item(parameters, "SE,ID"); if (!node) { - tsserror("ERROR: %s: Unable to find required SE,ID in parameters\n", __func__); + error("ERROR: %s: Unable to find required SE,ID in parameters\n", __func__); return -1; } plist_dict_set_item(request, "SE,ID", plist_copy(node)); @@ -1005,7 +1045,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid /* add SE,Nonce */ node = plist_dict_get_item(parameters, "SE,Nonce"); if (!node) { - tsserror("ERROR: %s: Unable to find required SE,Nonce in parameters\n", __func__); + error("ERROR: %s: Unable to find required SE,Nonce in parameters\n", __func__); return -1; } plist_dict_set_item(request, "SE,Nonce", plist_copy(node)); @@ -1014,7 +1054,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid /* add SE,RootKeyIdentifier */ node = plist_dict_get_item(parameters, "SE,RootKeyIdentifier"); if (!node) { - tsserror("ERROR: %s: Unable to find required SE,RootKeyIdentifier in parameters\n", __func__); + error("ERROR: %s: Unable to find required SE,RootKeyIdentifier in parameters\n", __func__); return -1; } plist_dict_set_item(request, "SE,RootKeyIdentifier", plist_copy(node)); @@ -1039,7 +1079,7 @@ int tss_request_add_se_tags(plist_t request, plist_t parameters, plist_t overrid break; if (!manifest_entry || plist_get_node_type(manifest_entry) != PLIST_DICT) { free(key); - tsserror("ERROR: Unable to fetch BuildManifest entry\n"); + error("ERROR: Unable to fetch BuildManifest entry\n"); return -1; } @@ -1088,7 +1128,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: Unable to get restore manifest from parameters\n"); + error("ERROR: Unable to get restore manifest from parameters\n"); return -1; } @@ -1099,7 +1139,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,UID */ node = plist_dict_get_item(parameters, "Savage,UID"); if (!node) { - tsserror("ERROR: Unable to find required Savage,UID in parameters\n"); + error("ERROR: Unable to find required Savage,UID in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,UID", plist_copy(node)); @@ -1108,7 +1148,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add SEP */ node = plist_access_path(manifest_node, 2, "SEP", "Digest"); if (!node) { - tsserror("ERROR: Unable to get SEP digest from manifest\n"); + error("ERROR: Unable to get SEP digest from manifest\n"); return -1; } plist_t dict = plist_new_dict(); @@ -1118,7 +1158,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,PatchEpoch */ node = plist_dict_get_item(parameters, "Savage,PatchEpoch"); if (!node) { - tsserror("ERROR: Unable to find required Savage,PatchEpoch in parameters\n"); + error("ERROR: Unable to find required Savage,PatchEpoch in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,PatchEpoch", plist_copy(node)); @@ -1127,7 +1167,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,ChipID */ node = plist_dict_get_item(parameters, "Savage,ChipID"); if (!node) { - tsserror("ERROR: Unable to find required Savage,ChipID in parameters\n"); + error("ERROR: Unable to find required Savage,ChipID in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,ChipID", plist_copy(node)); @@ -1136,7 +1176,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,AllowOfflineBoot */ node = plist_dict_get_item(parameters, "Savage,AllowOfflineBoot"); if (!node) { - tsserror("ERROR: Unable to find required Savage,AllowOfflineBoot in parameters\n"); + error("ERROR: Unable to find required Savage,AllowOfflineBoot in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,AllowOfflineBoot", plist_copy(node)); @@ -1145,7 +1185,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,ReadFWKey */ node = plist_dict_get_item(parameters, "Savage,ReadFWKey"); if (!node) { - tsserror("ERROR: Unable to find required Savage,ReadFWKey in parameters\n"); + error("ERROR: Unable to find required Savage,ReadFWKey in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,ReadFWKey", plist_copy(node)); @@ -1154,7 +1194,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,ProductionMode */ node = plist_dict_get_item(parameters, "Savage,ProductionMode"); if (!node) { - tsserror("ERROR: Unable to find required Savage,ProductionMode in parameters\n"); + error("ERROR: Unable to find required Savage,ProductionMode in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,ProductionMode", plist_copy(node)); @@ -1183,7 +1223,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,B?-*-Patch */ node = plist_dict_get_item(manifest_node, comp_name); if (!node) { - tsserror("ERROR: Unable to get %s entry from manifest\n", comp_name); + error("ERROR: Unable to get %s entry from manifest\n", comp_name); return -1; } dict = plist_copy(node); @@ -1197,7 +1237,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,Nonce */ node = plist_dict_get_item(parameters, "Savage,Nonce"); if (!node) { - tsserror("ERROR: Unable to find required Savage,Nonce in parameters\n"); + error("ERROR: Unable to find required Savage,Nonce in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,Nonce", plist_copy(node)); @@ -1206,7 +1246,7 @@ int tss_request_add_savage_tags(plist_t request, plist_t parameters, plist_t ove /* add Savage,ReadECKey */ node = plist_dict_get_item(parameters, "Savage,ReadECKey"); if (!node) { - tsserror("ERROR: Unable to find required Savage,ReadECKey in parameters\n"); + error("ERROR: Unable to find required Savage,ReadECKey in parameters\n"); return -1; } plist_dict_set_item(request, "Savage,ReadECKey", plist_copy(node)); @@ -1226,7 +1266,7 @@ int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t ov plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); return -1; } @@ -1237,7 +1277,7 @@ int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t ov /* add SEP */ node = plist_access_path(manifest_node, 2, "SEP", "Digest"); if (!node) { - tsserror("ERROR: Unable to get SEP digest from manifest\n"); + error("ERROR: Unable to get SEP digest from manifest\n"); return -1; } plist_t dict = plist_new_dict(); @@ -1250,7 +1290,7 @@ int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t ov for (i = 0; i < (int)(sizeof(keys) / sizeof(keys[0])); ++i) { node = plist_dict_get_item(parameters, keys[i]); if (!node) { - tsserror("ERROR: %s: Unable to find required %sin parameters\n", __func__, keys[i]); + error("ERROR: %s: Unable to find required %sin parameters\n", __func__, keys[i]); } plist_dict_set_item(request, keys[i], plist_copy(node)); node = NULL; @@ -1305,7 +1345,7 @@ int tss_request_add_yonkers_tags(plist_t request, plist_t parameters, plist_t ov free(iter); if (comp_name == NULL) { - tsserror("ERROR: No Yonkers node for %s/%lu\n", (isprod) ? "Production" : "Development", (unsigned long)fabrevision); + error("ERROR: No Yonkers node for %s/%lu\n", (isprod) ? "Production" : "Development", (unsigned long)fabrevision); return -1; } @@ -1336,7 +1376,7 @@ int tss_request_add_vinyl_tags(plist_t request, plist_t parameters, plist_t over plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); return -1; } @@ -1389,7 +1429,7 @@ int tss_request_add_rose_tags(plist_t request, plist_t parameters, plist_t overr plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); return -1; } @@ -1478,7 +1518,7 @@ int tss_request_add_veridian_tags(plist_t request, plist_t parameters, plist_t o plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); return -1; } @@ -1561,7 +1601,7 @@ int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overr plist_t manifest_node = plist_dict_get_item(parameters, "Manifest"); if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) { - tsserror("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); + error("ERROR: %s: Unable to get restore manifest from parameters\n", __func__); return -1; } @@ -1632,6 +1672,112 @@ int tss_request_add_tcon_tags(plist_t request, plist_t parameters, plist_t overr return 0; } +int tss_request_add_timer_tags(plist_t request, plist_t parameters, plist_t overrides) +{ + plist_t node = NULL; + uint64_t u64val = 0; + uint8_t bval = 0; + uint32_t tag = 0; + char *ticket_name = 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 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); + u64val = _plist_dict_get_uint(parameters, key); + plist_dict_set_item(request, key, plist_new_uint(u64val)); + + sprintf(key, "Timer,ChipID,%u", tag); + u64val = _plist_dict_get_uint(parameters, key); + plist_dict_set_item(request, key, plist_new_uint(u64val)); + + sprintf(key, "Timer,SecurityDomain,%u", tag); + u64val = _plist_dict_get_uint(parameters, key); + plist_dict_set_item(request, key, plist_new_uint(u64val)); + + sprintf(key, "Timer,SecurityMode,%u", tag); + bval = _plist_dict_get_bool(parameters, key); + plist_dict_set_item(request, key, plist_new_bool(bval)); + + sprintf(key, "Timer,ProductionMode,%u", tag); + bval = _plist_dict_get_bool(parameters, key); + plist_dict_set_item(request, key, plist_new_bool(bval)); + + sprintf(key, "Timer,ECID,%u", tag); + u64val = _plist_dict_get_uint(parameters, key); + plist_dict_set_item(request, key, plist_new_uint(u64val)); + + sprintf(key, "Timer,Nonce,%u", tag); + plist_t p_nonce = plist_dict_get_item(parameters, key); + plist_dict_set_item(request, key, plist_copy(p_nonce)); + + 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 */ + 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", 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; +} + 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) { @@ -1717,9 +1863,7 @@ char* tss_request_send_raw(char* request, const char* server_url_string, int* re info("failure\n"); } - if (response->length > 0) { - tsserror("TSS server returned: %s\n", response->content); - } + if (response->length > 0) {} char* status = strstr(response->content, "STATUS="); if (status) { @@ -1752,16 +1896,16 @@ char* tss_request_send_raw(char* request, const char* server_url_string, int* re // ignoring error that occurs when saving blobs on certain A8(X) devices and earlier break; } else { - tsserror("ERROR: tss_send_request: Unhandled status code %d\n", status_code); + 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="); - tsserror("ERROR: TSS request failed (status=%d, message=%s)\n", status_code, message); + error("TSS server returned: (status=%d, message=%s)\n", status_code, message); } else { - tsserror("ERROR: TSS request failed: %s (status=%d)\n", curl_error_message, status_code); + error("TSS server returned: %s (status=%d)\n", curl_error_message, status_code); } free(request); if (response) @@ -1794,7 +1938,7 @@ plist_t tss_request_send(plist_t tss_request, const char* server_url_string) { if (rsp){ char* tss_data = strstr(rsp, "size, i_vers->value,(int)i_build->size, i_build->value); + info("[TSSC] got firmwareurl for %.*s build %.*s\n",(int)i_vers->size, i_vers->value,(int)i_build->size, i_build->value); rets->version = (char*)malloc(i_vers->size+1); memcpy(rets->version, i_vers->value, i_vers->size); rets->version[i_vers->size] = '\0'; @@ -1038,15 +1047,20 @@ int isManifestBufSignedForDevice(char *buildManifestBuffer, t_devicevals *devVal plist_get_uint_val(pecid, &devVals->ecid); char *cecid = ecid_to_string(devVals->ecid); - uint32_t size = 0; - char* data = NULL; if (*devVals->generator) plist_dict_set_item(apticket, "generator", plist_new_string(devVals->generator)); if (apticket2) plist_dict_set_item(apticket, "updateInstall", apticket2); if (apticket3) plist_dict_set_item(apticket, "noNonce", apticket3); - plist_to_xml(apticket, &data, &size); + + uint32_t size = 0; + char* data = NULL; + + if (save_bplist) + plist_to_bin(apticket, &data, &size); + else + plist_to_xml(apticket, &data, &size); char *apnonce = ""; size_t apnonceLen = 0; @@ -1066,7 +1080,7 @@ int isManifestBufSignedForDevice(char *buildManifestBuffer, t_devicevals *devVal snprintf(tmpDevicename, tmpDeviceNameSize, "%s", devVals->deviceModel); if (devVals->deviceBoard) snprintf(tmpDevicename+strlen(tmpDevicename), tmpDeviceNameSize-strlen(tmpDevicename), "_%s",devVals->deviceBoard); - size_t fnamelen = strlen(shshSavePath) + 1 + strlen(cecid) + tmpDeviceNameSize + strlen(cpvers) + strlen(cbuild) + strlen(DIRECTORY_DELIMITER_STR"___-.shsh2") + 1; + size_t fnamelen = strlen(shshSavePath) + 1 + strlen(cecid) + tmpDeviceNameSize + strlen(cpvers) + strlen(cbuild) + strlen(DIRECTORY_DELIMITER_STR"___-.bshsh2") + 1; fnamelen += devVals->parsedApnonceLen*2; char *fname = malloc(fnamelen); @@ -1074,14 +1088,11 @@ int isManifestBufSignedForDevice(char *buildManifestBuffer, t_devicevals *devVal size_t prePathLen= strlen(shshSavePath); if (shshSavePath[prePathLen-1] == DIRECTORY_DELIMITER_CHR) prePathLen--; strncpy(fname, shshSavePath, prePathLen); - - snprintf(fname+prePathLen, fnamelen, DIRECTORY_DELIMITER_STR"%s_%s_%s-%s_%s.shsh%s",cecid,tmpDevicename,cpvers,cbuild, apnonce, (*devVals->generator || apticket2) ? "2" : ""); - - + snprintf(fname+prePathLen, fnamelen, DIRECTORY_DELIMITER_STR"%s_%s_%s-%s_%s.%sshsh%s",cecid,tmpDevicename,cpvers,cbuild, apnonce, save_bplist ? "b" : "", (*devVals->generator || apticket2) ? "2" : ""); FILE *shshfile = fopen(fname, "wb"); if (!shshfile) error("[Error] can't save shsh at %s\n",fname); else{ - fwrite(data, strlen(data), 1, shshfile); + fwrite(data, size, 1, shshfile); fclose(shshfile); info("Saved shsh blobs!\n"); } @@ -1192,7 +1203,7 @@ int isVersionSignedForDevice(jssytok_t *firmwareTokens, t_iosVersion *versVals, isSigned = (isSignedOne > 0 || isSigned > 0); if (buildManifest) (void)(free(buildManifest)), buildManifest = NULL; - info("Firmware version %s %s %s signed!\n",u->version,u->buildID,isSignedOne ? "IS" : "IS NOT"); + info("[INFO] Firmware version %s %s %s being signed.\n",u->version,u->buildID,isSignedOne ? "is" : "isn't"); } (void)(free(u->url)),u->url = NULL; (void)(free(u->buildID)),u->buildID = NULL; diff --git a/tsschecker/tsschecker.h b/tsschecker/tsschecker.h index 220e433f..6821ae10 100644 --- a/tsschecker/tsschecker.h +++ b/tsschecker/tsschecker.h @@ -24,6 +24,7 @@ extern int dbglog; extern int print_tss_response; extern int nocache; extern int save_shshblobs; +extern int save_bplist; extern const char *shshSavePath; struct bbdevice{