summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml33
-rw-r--r--README.md223
-rw-r--r--configure.ac35
-rw-r--r--src/Makefile.am5
-rw-r--r--src/asr.c34
-rw-r--r--src/asr.h4
-rw-r--r--src/common.c36
-rw-r--r--src/common.h1
-rw-r--r--src/fixedint.h72
-rw-r--r--src/idevicerestore.c23
-rw-r--r--src/ipsw.c18
-rw-r--r--src/restore.c987
-rw-r--r--src/restore.h17
-rw-r--r--src/sha1.c294
-rw-r--r--src/sha1.h44
-rw-r--r--src/sha512.c314
-rw-r--r--src/sha512.h32
17 files changed, 1101 insertions, 1071 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 76d4a0b..bd2bdd5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -48,6 +48,13 @@ jobs:
workflow: build.yml
name: libimobiledevice-latest_${{env.target_triplet}}
repo: libimobiledevice/libimobiledevice
+ - name: fetch libtatsu
+ uses: dawidd6/action-download-artifact@v3
+ with:
+ github_token: ${{secrets.GITHUB_TOKEN}}
+ workflow: build.yml
+ name: libtatsu-latest_${{env.target_triplet}}
+ repo: libimobiledevice/libtatsu
- name: install external dependencies
run: |
mkdir extract
@@ -122,6 +129,13 @@ jobs:
workflow: build.yml
name: libimobiledevice-latest_macOS
repo: libimobiledevice/libimobiledevice
+ - name: fetch libtatsu
+ uses: dawidd6/action-download-artifact@v3
+ with:
+ github_token: ${{secrets.GITHUB_TOKEN}}
+ workflow: build.yml
+ name: libtatsu-latest_macOS
+ repo: libimobiledevice/libtatsu
- name: install external dependencies
run: |
mkdir extract
@@ -144,18 +158,7 @@ jobs:
export CFLAGS="$USEARCHS -isysroot $SDKDIR"
echo "Using CFLAGS: $CFLAGS"
echo "BUILD_CFLAGS=$CFLAGS" >> $GITHUB_ENV
- mkdir -p lib
- curl -o lib/libcrypto.35.tbd -Ls \
- https://gist.github.com/nikias/94c99fd145a75a5104415e5117b0cafa/raw/5209dfbff5a871a14272afe4794e76eb4cf6f062/libcrypto.35.tbd
- curl -o lib/libssl.35.tbd -Ls \
- https://gist.github.com/nikias/94c99fd145a75a5104415e5117b0cafa/raw/5209dfbff5a871a14272afe4794e76eb4cf6f062/libssl.35.tbd
- LIBRESSL_VER=2.2.7
- FILENAME="libressl-$LIBRESSL_VER.tar.gz"
- curl -o $FILENAME -Ls "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/$FILENAME"
mkdir -p deps
- tar -C deps -xzf $FILENAME
- echo "LIBRESSL_CFLAGS=-I`pwd`/deps/libressl-$LIBRESSL_VER/include" >> $GITHUB_ENV
- echo "LIBRESSL_LIBS=-Xlinker `pwd`/lib/libssl.35.tbd -Xlinker `pwd`/lib/libcrypto.35.tbd" >> $GITHUB_ENV
FILENAME="libzip-static.tar.bz2"
curl -o $FILENAME.b64 -Ls "https://gist.github.com/nikias/3da15d03120382f87b44029cd8495a02/raw/99cd8138fed99e8f6530b6f179f787342c698e1f/libzip-1.7.1_static_macOS.tar.bz2"
base64 -D < $FILENAME.b64 > $FILENAME
@@ -167,7 +170,6 @@ jobs:
export CFLAGS="${{env.BUILD_CFLAGS}} -Wno-nullability-completeness -Wno-expansion-to-defined"
echo "Using CFLAGS: $CFLAGS"
./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig \
- openssl_CFLAGS="$LIBRESSL_CFLAGS" openssl_LIBS="$LIBRESSL_LIBS" \
libcurl_CFLAGS="-I${{env.SDKDIR}}/usr/include" libcurl_LIBS="-lcurl" \
libzip_CFLAGS="$LIBZIP_CFLAGS" libzip_LIBS="$LIBZIP_LIBS" \
zlib_CFLAGS="-I${{env.SDKDIR}}/usr/include" zlib_LIBS="-lz" \
@@ -253,6 +255,13 @@ jobs:
workflow: build.yml
name: libimobiledevice-latest_${{ matrix.arch }}-${{ env.dest }}
repo: libimobiledevice/libimobiledevice
+ - name: fetch libtatsu
+ uses: dawidd6/action-download-artifact@v3
+ with:
+ github_token: ${{secrets.GITHUB_TOKEN}}
+ workflow: build.yml
+ name: libtatsu-latest_${{ matrix.arch }}-${{ env.dest }}
+ repo: libimobiledevice/libtatsu
- name: install external dependencies
run: |
mkdir extract
diff --git a/README.md b/README.md
index 3b52567..1af2d93 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,21 @@
![](https://github.com/libimobiledevice/idevicerestore/actions/workflows/build.yml/badge.svg)
+## Table of Contents
+- [Features](#features)
+- [Building](#building)
+ - [Prerequisites](#prerequisites)
+ - [Linux (Debian/Ubuntu based)](#linux-debianubuntu-based)
+ - [macOS](#macos)
+ - [Windows](#windows)
+ - [Configuring the source tree](#configuring-the-source-tree)
+ - [Building and installation](#building-and-installation)
+- [Usage](#usage)
+- [Contributing](#contributing)
+- [Links](#links)
+- [License](#license)
+- [Credits](#credits)
+
## Features
The idevicerestore application is a full reimplementation of all granular steps
@@ -33,56 +48,176 @@ Use with caution and make sure to backup your data before trying to restore.
**In any case, usage is at your own risk.**
-## Installation / Getting started
-
-### Debian / Ubuntu Linux
+## Building
+
+### Prerequisites
+
+You need to have a working compiler (gcc/clang) and development environent
+available. This project uses autotools for the build process, allowing to
+have common build steps across different platforms.
+Only the prerequisites differ and they are described in this section.
+
+#### Linux (Debian/Ubuntu based)
+
+* Install all required dependencies and build tools:
+ ```shell
+ sudo apt-get install \
+ build-essential \
+ pkg-config \
+ checkinstall \
+ git \
+ autoconf \
+ automake \
+ libtool-bin \
+ libreadline-dev \
+ libusb-1.0-0-dev \
+ libplist-dev \
+ libimobiledevice-dev \
+ libimobiledevice-glue-dev \
+ libtatsu-dev \
+ libcurl4-openssl-dev \
+ libssl-dev \
+ libzip-dev \
+ zlib1g-dev
+ ```
+ NOTE: [libtatsu](https://github.com/libimobiledevice/libtatsu) (and thus `libtatsu-dev`)
+ is a new library that was just published recently, you have to
+ [build it from source](https://github.com/libimobiledevice/libtatsu?tab=readme-ov-file#building).
+ Also, other `*-dev` packages might not be available for your distribution,
+ so you will have to build these packages on your own as well.
+
+#### macOS
+
+* Make sure the Xcode command line tools are installed.
+
+ **Option 1**:
+ The easiest way to build and install `idevicerestore` for macOS is using
+ the following build script which will do the work for you, it will build
+ and install all required dependencies:
+ ```bash
+ mkdir -p limd-build
+ cd limd-build
+ curl -o ./limd-build-macos.sh -L https://is.gd/limdmacos
+ bash ./limd-build-macos.sh
+ ```
+ Follow the prompts of the script and you should have a working `idevicerestore`
+ available.
+
+ **Option 2**:
+ Use either [MacPorts](https://www.macports.org/)
+ or [Homebrew](https://brew.sh/) to install `automake`, `autoconf`, and `libtool`.
+
+ Using MacPorts:
+ ```shell
+ sudo port install libtool autoconf automake
+ ```
+
+ Using Homebrew:
+ ```shell
+ brew install libtool autoconf automake
+ ```
+
+ `idevicerestore` has a few dependencies from the libimobiledevice project.
+ You will have to build and install the following:
+ * [libplist](https://github.com/libimobiledevice/libplist)
+ * [libimobiledevice-glue](https://github.com/libimobiledevice/libimobiledevice-glue)
+ * [libusbmuxd](https://github.com/libimobiledevice/libusbmuxd)
+ * [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)
+ * [libirecovery](https://github.com/libimobiledevice/libirecovery)
+ * [libtatsu](https://github.com/libimobiledevice/libtatsu)
+
+ Check their `README.md` for building and installation instructions.
+
+#### Windows
+
+* Using [MSYS2](https://www.msys2.org/) is the official way of compiling this project on Windows. Download the MSYS2 installer
+ and follow the installation steps.
+
+ It is recommended to use the _MSYS2 MinGW 64-bit_ shell. Run it and make sure the required dependencies are installed:
+
+ ```shell
+ pacman -S base-devel \
+ git \
+ mingw-w64-x86_64-gcc \
+ make \
+ libtool \
+ autoconf \
+ automake-wrapper
+ ```
+ NOTE: You can use a different shell and different compiler according to your needs. Adapt the above command accordingly.
+
+ `idevicerestore` has a few dependencies from the libimobiledevice project.
+ You will have to build and install the following:
+ * [libplist](https://github.com/libimobiledevice/libplist)
+ * [libimobiledevice-glue](https://github.com/libimobiledevice/libimobiledevice-glue)
+ * [libusbmuxd](https://github.com/libimobiledevice/libusbmuxd)
+ * [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)
+ * [libirecovery](https://github.com/libimobiledevice/libirecovery)
+ * [libtatsu](https://github.com/libimobiledevice/libtatsu)
+
+ Check their `README.md` for building and installation instructions.
+
+
+### Configuring the source tree
+
+You can build the source code from a git checkout, or from a `.tar.bz2` release tarball from [Releases](https://github.com/libimobiledevice/idevicerestore/releases).
+Before we can build it, the source tree has to be configured for building. The steps depend on where you got the source from.
+
+* **From git**
+
+ If you haven't done already, clone the actual project repository and change into the directory.
+ ```shell
+ git clone https://github.com/libimobiledevice/idevicerestore.git
+ cd idevicerestore
+ ```
+
+ Configure the source tree for building:
+ ```shell
+ ./autogen.sh
+ ```
+
+* **From release tarball (.tar.bz2)**
+
+ When using an official [release tarball](https://github.com/libimobiledevice/idevicerestore/releases) (`idevicerestore-x.y.z.tar.bz2`)
+ the procedure is slightly different.
+
+ Extract the tarball:
+ ```shell
+ tar xjf idevicerestore-x.y.z.tar.bz2
+ cd idevicerestore-x.y.z
+ ```
+
+ Configure the source tree for building:
+ ```shell
+ ./configure
+ ```
+
+Both `./configure` and `./autogen.sh` (which generates and calls `configure`) accept a few options, for example `--prefix` to allow
+building for a different target folder. You can simply pass them like this:
-First install all required dependencies and build tools:
```shell
-sudo apt-get install \
- build-essential \
- pkg-config \
- checkinstall \
- git \
- autoconf \
- automake \
- libtool-bin \
- libreadline-dev \
- libusb-1.0-0-dev \
- libplist-dev \
- libimobiledevice-dev \
- libimobiledevice-glue-dev \
- libcurl4-openssl-dev \
- libssl-dev \
- libzip-dev \
- zlib1g-dev
+./autogen.sh --prefix=/usr/local
```
-
-Then clone, build and install [libirecovery](https://github.com/libimobiledevice/libirecovery.git) which is not yet packaged:
+or
```shell
-git clone https://github.com/libimobiledevice/libirecovery.git
-cd libirecovery
-./autogen.sh
-make
-sudo make install
-cd ..
+./configure --prefix=/usr/local
```
-If the configure processes indicates old or missing libraries, your distribution
-might not have yet packaged the latest versions. In that case you will have to
-clone [these libraries](https://github.com/libimobiledevice/) separately and repeat the process in order to proceed.
-
-Continue with cloning the actual project repository:
-```shell
-git clone https://github.com/libimobiledevice/idevicerestore.git
-cd idevicerestore
+Once the command is successful, the last few lines of output will look like this:
```
+[...]
+config.status: creating config.h
+config.status: config.h is unchanged
+config.status: executing depfiles commands
+config.status: executing libtool commands
-Now you can build and install it:
-```shell
-./autogen.sh
-make
-sudo make install
+Configuration for idevicerestore 1.1.0:
+-------------------------------------------
+
+ Install prefix: .........: /usr/local
+
+ Now type 'make' to build idevicerestore 1.1.0,
+ and then 'make install' for installation.
```
**Important**
@@ -142,8 +277,6 @@ Please make sure your contribution adheres to:
* Try to split larger changes into individual commits of a common domain
* Use your real name and a valid email address for your commits
-We are still working on the guidelines so bear with us!
-
## Links
* Homepage: https://libimobiledevice.org/
@@ -166,4 +299,4 @@ iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc.
This project is an independent software application and has not been
authorized, sponsored, or otherwise approved by Apple Inc.
-README Updated on: 2022-04-04
+README Updated on: 2024-06-19
diff --git a/configure.ac b/configure.ac
index 4686e19..d0a052f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,11 +19,10 @@ LIBIRECOVERY_VERSION=1.2.0
LIBIMOBILEDEVICE_VERSION=1.3.0
LIBUSBMUXD_VERSION=2.0.2
LIBPLIST_VERSION=2.6.0
-LIMD_GLUE_VERSION=1.2.0
-LIBTATSU_VERSION=1.0.0
+LIMD_GLUE_VERSION=1.3.0
+LIBTATSU_VERSION=1.0.3
LIBZIP_VERSION=1.0
LIBCURL_VERSION=7.0
-OPENSSL_VERSION=0.9.8
AC_SUBST(LIBIRECOVERY_VERSION)
AC_SUBST(LIBIMOBILEDEVICE_VERSION)
@@ -33,7 +32,6 @@ AC_SUBST(LIMD_GLUE_VERSION)
AC_SUBST(LIBTATSU_VERSION)
AC_SUBST(LIBZIP_VERSION)
AC_SUBST(LIBCURL_VERSION)
-AC_SUBST(OPENSSL_VERSION)
# Checks for programs.
AC_PROG_CC
@@ -51,9 +49,6 @@ PKG_CHECK_MODULES(libzip, libzip >= $LIBZIP_VERSION)
PKG_CHECK_MODULES(libcurl, libcurl >= $LIBCURL_VERSION)
PKG_CHECK_MODULES(zlib, zlib)
-# optional
-PKG_CHECK_MODULES(openssl, openssl >= $OPENSSL_VERSION, have_openssl=yes, have_openssl=no)
-
AC_CHECK_FUNCS([strsep strcspn mkstemp realpath])
if test x$ac_cv_func_strsep != xyes; then
if test x$ac_cv_func_strcspn != xyes; then
@@ -156,32 +151,6 @@ fi
CFLAGS="$CACHED_CFLAGS"
-AC_ARG_WITH([openssl],
- [AS_HELP_STRING([--without-openssl],
- [Do not use OpenSSL])],
- [use_openssl=$withval],
- [use_openssl=$have_openssl])
-
-if test "x$use_openssl" == "xyes"; then
- if test "x$have_openssl" != "xyes"; then
- echo "*** NOTE: --with-openssl passed but OpenSSL is not available ***"
- use_openssl=no
- fi
-fi
-if test "x$use_openssl" != "xyes"; then
- echo "*** NOTE: Using internal SHA1 implementation ***"
- have_openssl=no
- openssl_CFLAGS=
- openssl_LIBS=
-fi
-if test "x$have_openssl" == "xyes"; then
- AC_DEFINE(HAVE_OPENSSL, [1], [Define if you have OpenSSL])
-fi
-AC_SUBST(openssl_CFLAGS)
-AC_SUBST(openssl_LIBS)
-
-AM_CONDITIONAL(USE_INTERNAL_SHA, test x$use_openssl != xyes)
-
AC_SUBST(GLOBAL_CFLAGS)
AC_SUBST(AC_LDFLAGS)
AC_SUBST(AC_LDADD)
diff --git a/src/Makefile.am b/src/Makefile.am
index 88602e5..80f02f2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,7 +9,6 @@ AM_CFLAGS = \
$(libtatsu_CFLAGS) \
$(libzip_CFLAGS) \
$(zlib_CFLAGS) \
- $(openssl_CFLAGS) \
$(libcurl_CFLAGS)
AM_LDFLAGS = \
@@ -22,7 +21,6 @@ AM_LDFLAGS = \
$(libtatsu_LIBS) \
$(libzip_LIBS) \
$(zlib_LIBS) \
- $(openssl_LIBS) \
$(libcurl_LIBS)
AM_LDADD = $(AC_LDADD)
@@ -50,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)
diff --git a/src/asr.c b/src/asr.c
index bf15dc2..b150e85 100644
--- a/src/asr.c
+++ b/src/asr.c
@@ -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;
}
diff --git a/src/asr.h b/src/asr.h
index 0d9534c..4473fbb 100644
--- a/src/asr.h
+++ b/src/asr.h
@@ -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 e5ee07b..80d8256 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,31 @@ 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)
+{
+ printf("******** _log_init ********\n");
+ 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 +114,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 +123,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 +246,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 +258,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 +483,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 +493,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
diff --git a/src/common.h b/src/common.h
index 766a385..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[];
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 0b517b9..8de9186 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -38,13 +38,7 @@
#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>
@@ -1495,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;
@@ -1520,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)
@@ -2170,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) {
@@ -2495,7 +2490,7 @@ 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));
@@ -2590,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));
@@ -2603,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 */
diff --git a/src/ipsw.c b/src/ipsw.c
index c25f61d..6a747f4 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -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>
@@ -1176,14 +1168,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;
}
diff --git a/src/restore.c b/src/restore.c
index efb03f9..a62886d 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
@@ -39,6 +41,7 @@
#include <zip.h>
#include <libirecovery.h>
#include <libtatsu/tss.h>
+#include <curl/curl.h>
#include "idevicerestore.h"
#include "asr.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);
+ 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);
}
@@ -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);
@@ -1387,8 +1774,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
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);
@@ -1412,8 +1799,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
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);
@@ -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;
}
@@ -1820,7 +2214,7 @@ leave:
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;
@@ -1834,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!
@@ -1870,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);
@@ -1884,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);
@@ -1911,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);
@@ -1965,12 +2364,20 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer
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;
@@ -1986,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;
@@ -1998,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;
@@ -2011,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;
@@ -2024,6 +2438,11 @@ 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);
node = plist_dict_get_item(arguments, "ImageName");
@@ -2051,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);
}
@@ -2083,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);
}
@@ -2110,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);
@@ -2128,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);
@@ -2155,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;
@@ -2167,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);
@@ -2177,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");
@@ -2196,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;
}
@@ -2220,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(&parameters, p_info);
@@ -2255,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)
{
char *comp_name = NULL;
char *comp_path = NULL;
@@ -2267,6 +2699,11 @@ 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;
+ }
+
/* create Savage request */
request = tss_request_new(NULL);
if (request == NULL) {
@@ -2277,7 +2714,7 @@ 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(&parameters, p_info);
@@ -2310,7 +2747,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;
@@ -2346,7 +2783,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)
{
char *comp_name = NULL;
char *comp_path = NULL;
@@ -2357,6 +2794,11 @@ 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;
+ }
+
/* create Yonkers request */
request = tss_request_new(NULL);
if (request == NULL) {
@@ -2369,7 +2811,7 @@ 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(&parameters, p_info);
@@ -2401,7 +2843,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;
@@ -2430,7 +2872,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;
@@ -2444,6 +2886,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) {
@@ -2455,7 +2902,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) {
@@ -2501,7 +2948,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;
}
@@ -2525,8 +2972,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;
@@ -2577,7 +3024,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)
{
char *comp_name = "BMU,FirmwareMap";
char *comp_path = NULL;
@@ -2588,6 +3035,11 @@ 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;
+ }
+
/* create Veridian request */
request = tss_request_new(NULL);
if (request == NULL) {
@@ -2599,7 +3051,7 @@ 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(&parameters, p_info);
@@ -2624,7 +3076,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;
}
@@ -2653,7 +3105,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);
@@ -2673,7 +3125,7 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str
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;
@@ -2728,7 +3180,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)
{
char *comp_name = "Baobab,TCON";
char *comp_path = NULL;
@@ -2739,6 +3191,11 @@ 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;
+ }
+
/* create Baobab request */
request = tss_request_new(NULL);
if (request == NULL) {
@@ -2750,7 +3207,7 @@ 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(&parameters, p_info);
@@ -2775,7 +3232,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;
}
@@ -2797,7 +3254,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)
{
char comp_name[64];
char *comp_path = NULL;
@@ -2813,6 +3270,11 @@ 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;
+ }
+
/* create Timer request */
request = tss_request_new(NULL);
if (request == NULL) {
@@ -2823,7 +3285,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) {
@@ -2902,8 +3364,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;
}
@@ -2930,8 +3392,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;
@@ -2982,12 +3444,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);
@@ -3019,7 +3486,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));
}
@@ -3034,10 +3501,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 */
@@ -3072,7 +3539,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;
@@ -3082,11 +3549,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;
@@ -3096,7 +3570,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;
@@ -3107,6 +3581,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);
@@ -3153,7 +3632,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;
@@ -3163,59 +3642,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);
} else {
- fwdict = restore_get_savage_firmware_data(restore, client, build_identity, p_info);
+ fwdict = restore_get_savage_firmware_data(client, p_info);
}
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);
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);
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);
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;
@@ -3224,12 +3703,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;
@@ -3246,23 +3732,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;
@@ -3379,7 +3877,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__);
@@ -3395,9 +3893,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;
}
@@ -3442,16 +3945,16 @@ 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");
+ plist_t args = plist_dict_get_item(message, "Arguments");
return restore_get_build_identity(client, plist_dict_get_bool(args, "IsRecoveryOS"));
}
@@ -3531,7 +4034,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;
};
@@ -3545,13 +4048,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);
@@ -3563,15 +4075,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;
@@ -3593,7 +4105,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;
}
@@ -3617,7 +4129,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;
@@ -3649,11 +4161,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;
@@ -3661,6 +4179,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;
}
@@ -3670,19 +4189,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;
@@ -3707,7 +4228,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;
@@ -3718,7 +4239,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) {
@@ -3731,7 +4252,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;
@@ -3747,25 +4268,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;
@@ -3782,7 +4312,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;
@@ -3799,7 +4329,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;
@@ -3811,19 +4349,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 {
@@ -3831,7 +4375,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);
@@ -3842,7 +4387,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;
@@ -3851,38 +4396,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;
}
@@ -3890,7 +4435,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;
}
@@ -3898,7 +4443,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;
}
@@ -3906,35 +4451,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;
}
@@ -3942,7 +4487,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;
}
@@ -3953,75 +4498,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);
@@ -4032,6 +4591,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()
{
@@ -4098,6 +4721,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;
}
@@ -4118,6 +4745,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;
}
@@ -4157,6 +4787,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;
@@ -4354,6 +4985,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");
@@ -4456,7 +5099,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
@@ -4473,7 +5131,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"));
@@ -4492,7 +5150,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
@@ -4502,7 +5161,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
@@ -4528,12 +5188,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
@@ -4548,6 +5222,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