21 Commits

Author SHA1 Message Date
Andrew Gunnerson 904a9f666a Add end-to-end patching tests
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-13 22:14:27 -05:00
Andrew Gunnerson 0f3bb92ab3 avbroot.py: Validate Magisk apk version
This helps guard against future directory structure changes. So far,
this has remained the same across Magisk versions 22 through 25.2.

The check can be overridden with `--ignore-magisk-version`.

Issue: #37

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-13 17:25:27 -05:00
Andrew Gunnerson 51a3742837 avbroot.py: Run boot image patches in parallel
There are no interdependencies across different boot images, so run the
patches in parallel. It only saves a few seconds, but it's a free
optimization.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-12 18:01:48 -05:00
Andrew Gunnerson 6a5ce3815e avbroot.py: extract: Create output directory if it doesn't already exist
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-11 18:12:04 -05:00
Andrew Gunnerson 2c4ab013b0 avbroot.py: Make script executable
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-11 18:11:12 -05:00
Andrew Gunnerson 6c116f0dba Remove dependency on magiskboot
This commit reimplements the magiskboot patching process natively in
Python. By doing so, avbroot gains cross platform support and there's no
longer a need to execute an Android binary on a non-Android Linux system,
which had pitfalls that already had to be worked around.

Boot images and cpio archives are handled by new custom parsers added to
avbroot. Legacy lz4 compression is done by a wrapper around the python
lz4 library (a new dependency). Gzip compression is handled natively by
python. Other compression methods and OEM-specific boot image formats
are not supported because devices that use the modern Android A/B OTA
scheme do not use those.

Output files are still bit-for-bit reproducible across runs, but they
are different from what prior avbroot commits produced:

* avbroot's cpio writer follows GNU cpio and libarchive's behavior of
  setting the mode field to 0 in the trailer entry. magiskboot sets the
  mode to 0o755.
* When patching a vendor boot v4 image, the ramdisk table entries are
  now updated correctly. Prior vendor boot images were only bootable
  because:

  * the image only contained a single ramdisk
  * the single ramdisk shrunk in size, stayed the same, or grew little
    enough to not exceed a page boundary
  * the bootloader is lenient in validating boot image fields

  magiskboot does not handle vendor boot v4 images correctly, but it
  doesn't need to just for the regular root patch. avbroot made use of
  it in an unsupported way to patch vendor boot ramdisks.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-11 01:22:24 -05:00
Andrew Gunnerson 17ee5ee37b Pass encrypted private keys to openssl directly
openssl supports passing the passphrase via a file descriptor, so let's
do that and avoid ever putting plaintext private keys on the filesystem,
even if it is a tmpfs.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-09 22:20:06 -05:00
Pascal Roeleven 9618c0bc36 Add unused return object when extracting
Fixes #34
2023-02-07 22:17:04 +01:00
Andrew Gunnerson 3c843856e1 Add support for OnePlus OTAs
Only OxygenOS 12 and 13 can work because older builds use the legacy
metadata file instead of the newer protobuf format.

Differences from Pixel devices:

* There's a recovery image. It contains otacerts.zip instead of
  vendor_boot or boot. The image uses a version 4 `ANDROID!` header, not
  `VNDRBOOT`.
* The payload.bin uses ZERO blocks with no sha256 checksum.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-06 22:52:05 -05:00
Andrew Gunnerson 2d4ff61531 Stop setting default temporary directory to the output directory
Now that avbroot no longer needs to create huge temp files, just use the
OS's default temp directory.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-03 17:38:18 -05:00
Andrew Gunnerson 806d8117f0 Perform all OTA signing ourselves
With this commit, avbroot now performs the entire OTA signing process
itself. This removes the 4 full .zip builds needed for signing before,
which means that avbroot can now do the full patching process in a
single pass.

Since signapk is no longer needed, the java dependency has been dropped.
This also means that avbroot no longer depends on glibc-based Linux
distros, which was the case before due to signapk's conscrypt
dependency.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-02-01 22:29:01 -05:00
Andrew Gunnerson df887f90e7 ota: Reimplement zip signing ourselves more efficiently
The original AOSP ota_utils implementation is quite disk and memory heavy:

* ota_utils.FinalizeMetadata() performs metadata file replacement as
  separate delete + add operations, which require an extra intermediate
  zip to be written.
* ota_utils.FinalizeMetadata() keeps unneeded intermediate temporary
  files around until common.Cleanup() is called.
* common.ZipDelete() deletes files by excluding entries when copying
  from one zip to another. The data copy reads entire entries (including
  the huge payload) into memory instead of copying chunks.

Additionally, ota_utils is a bit exception/crash-unsafe in general.
There are several places where temp files won't be cleaned up unless
everything is following the happy path.

This commit's reimplementation tries to use streaming and chunked
operations where possible and only keeps temporary files around as long
as needed. This is about as efficient as we can get while still relying
on AOSP's signapk.

(And we can finally get rid of the common.OPTIONS hackery!)

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-01-30 19:52:00 -05:00
Andrew Gunnerson c2f64a6587 avbroot.py: Add final status message to indicate the elapsed time
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-01-30 13:54:59 -05:00
Andrew Gunnerson d67cc7fe11 Respect standard TMPDIR/TEMP/TMP environment variables
If any standard temp directory environment variables are set, then don't
use the output directory as the temp directory.

Issue: #22

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2023-01-28 16:20:48 -05:00
Andrew Gunnerson 41e7d347e2 avbroot.py: Use the output directory as the default temporary directory path
Systems where /tmp is on a tmpfs and have less free RAM may have trouble
with the patching process.

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2023-01-24 19:52:57 -05:00
Andrew Gunnerson aed3ce6494 avbroot: Decrypt keys to tmpfs on Linux if available
Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2023-01-24 18:47:52 -05:00
Andrew Gunnerson 6c8333a866 avbroot.py: Decrypt keys to standard temp directory
Using /dev/shm breaks compatibility with non-Linux operating systems. On
Linux, most distros mount /tmp as a tmpfs anyway.

Fixes: #15

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2023-01-21 01:21:12 -05:00
Andrew Gunnerson c83b8f5b17 Add support for older Pixel devices
* Apply OTA certificate patch to the boot image if no `vendor_boot`
  image exists.
* Only manually decompress ramdisk cpio archives if the boot image
  header version is 4. `magiskboot` automatically decompresses older
  header versions.

Fixes: #5

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2022-11-27 17:12:11 -05:00
Andrew Gunnerson dbaa3b8b40 avbroot.py: Add support for init_boot image
Devices launching with Android 13, like the Pixel 7 series, put the
ramdisk containing first stage init in the init_boot partition instead
of the boot partition.

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2022-10-13 17:24:19 -04:00
Andrew Gunnerson 985325d26c Switch to OTA patching
This is more secure and reliable compared to forcibly enabling fastbootd
in recovery. All of the normal AVB and OTA update flows are preserved,
except with the user's custom keys.

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2022-07-02 16:17:13 -04:00
Andrew Gunnerson b87178b628 Initial commit
Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
2022-06-25 19:14:20 -04:00