diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java index 01292beab..d42c0bfa4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java @@ -19,15 +19,13 @@ public class DownloadBusybox extends ParallelTask { private static final String BUSYBOX_ARM = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-arm"; private static final String BUSYBOX_X86 = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-x86"; - private File busybox; - @Override protected Void doInBackground(Void... voids) { Context context = MagiskManager.get(); - busybox = new File(context.getCacheDir(), "busybox"); + File busybox = new File(context.getCacheDir(), "busybox"); Utils.removeItem(context.getApplicationInfo().dataDir + "/busybox"); - try { - FileOutputStream out = new FileOutputStream(busybox); + try (FileOutputStream out = new FileOutputStream(busybox)) { + HttpURLConnection conn = WebService.request( Build.SUPPORTED_32_BIT_ABIS[0].contains("x86") ? BUSYBOX_X86 : @@ -36,12 +34,7 @@ public class DownloadBusybox extends ParallelTask { ); if (conn == null) throw new IOException(); BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); - byte[] buffer = new byte[4096]; - int len; - while ((len = bis.read(buffer)) != -1) { - out.write(buffer, 0, len); - } - out.close(); + Utils.inToOut(bis, out); conn.disconnect(); } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java index 2dce04092..9510779fb 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java @@ -64,10 +64,7 @@ public class FlashZip extends ParallelTask { ) { if (in == null) throw new FileNotFoundException(); InputStream buf= new BufferedInputStream(in); - byte buffer[] = new byte[4096]; - int length; - while ((length = buf.read(buffer)) > 0) - out.write(buffer, 0, length); + Utils.inToOut(buf, out); } catch (FileNotFoundException e) { mList.add("! Invalid Uri"); throw e; diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java index ead86f381..a479d510c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java @@ -1,11 +1,13 @@ package com.topjohnwu.magisk.asyncs; import android.app.Activity; +import android.content.res.AssetManager; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.text.TextUtils; +import com.topjohnwu.crypto.SignBoot; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.container.AdaptiveList; import com.topjohnwu.magisk.container.TarEntry; @@ -103,6 +105,7 @@ public class InstallMagisk extends ParallelTask { ZipUtils.unzip(buf, install, "chromeos/", false); buf.reset(); ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true); + buf.close(); } catch (FileNotFoundException e) { mList.add("! Invalid Uri"); throw e; @@ -111,10 +114,9 @@ public class InstallMagisk extends ParallelTask { throw e; } - File boot; + File boot = new File(install, "boot.img"); switch (mode) { case PATCH_MODE: - boot = new File(install, "boot.img"); // Copy boot image to local try ( InputStream in = mm.getContentResolver().openInputStream(mBootImg); @@ -136,10 +138,7 @@ public class InstallMagisk extends ParallelTask { // Direct copy raw image source = new BufferedInputStream(in); } - byte buffer[] = new byte[1024]; - int length; - while ((length = source.read(buffer)) > 0) - out.write(buffer, 0, length); + Utils.inToOut(source, out); } catch (FileNotFoundException e) { mList.add("! Invalid Uri"); throw e; @@ -147,26 +146,41 @@ public class InstallMagisk extends ParallelTask { mList.add("! Copy failed"); throw e; } + mList.add("- Use boot image: " + boot); break; case DIRECT_MODE: - boot = new File(mBootLocation); + try (OutputStream out = new FileOutputStream(boot)) { + Process process = Runtime.getRuntime().exec(new String[] { "su", "-c", "cat " + mBootLocation }); + Utils.inToOut(process.getInputStream(), out); + process.waitFor(); + process.destroy(); + } catch (Exception e) { + mList.add("! Dump boot image failed"); + throw e; + } + mList.add("- Use boot image: " + mBootLocation); break; default: return false; } - mList.add("- Use boot image: " + boot); - - Shell shell; - if (mode == PATCH_MODE && Shell.rootAccess()) { - // Force non-root shell - shell = new Shell("sh"); - } else { - shell = Shell.getShell(); + boolean isSigned; + try (InputStream in = new FileInputStream(boot)) { + isSigned = SignBoot.verifySignature(in, null); + if (isSigned) { + mList.add("- Signed boot image detected"); + } + } catch (Exception e) { + mList.add("! Unable to check signature"); + throw e; } - if (shell == null) - return false; + // Force non-root shell + Shell shell; + if (Shell.rootAccess()) + shell = new Shell("sh"); + else + shell = Shell.getShell(); // Patch boot image shell.run(mList, @@ -180,6 +194,22 @@ public class InstallMagisk extends ParallelTask { return false; File patched_boot = new File(install, "new-boot.img"); + + if (isSigned) { + mList.add("- Signing boot image"); + File signed = new File(install, "signed.img"); + AssetManager assets = mm.getAssets(); + try ( + InputStream in = new FileInputStream(patched_boot); + OutputStream out = new BufferedOutputStream(new FileOutputStream(signed)); + InputStream keyIn = assets.open(ZipUtils.PRIVATE_KEY_NAME); + InputStream certIn = assets.open(ZipUtils.PUBLIC_KEY_NAME) + ) { + SignBoot.doSignature("/boot", in, out, keyIn, certIn); + } + shell.run_raw(false, "mv -f " + signed + " " + patched_boot); + } + mList.add(""); switch (mode) { case PATCH_MODE: @@ -190,17 +220,13 @@ public class InstallMagisk extends ParallelTask { shell.run_raw(false, "cp -f " + patched_boot + " " + dest); break; case ".img.tar": - TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest))); - tar.putNextEntry(new TarEntry(patched_boot, "boot.img")); - byte buffer[] = new byte[4096]; - BufferedInputStream in = new BufferedInputStream(new FileInputStream(patched_boot)); - int len; - while ((len = in.read(buffer)) != -1) { - tar.write(buffer, 0, len); + try ( + TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest))); + InputStream in = new FileInputStream(patched_boot) + ) { + tar.putNextEntry(new TarEntry(patched_boot, "boot.img")); + Utils.inToOut(in, tar); } - tar.flush(); - tar.close(); - in.close(); break; } mList.add("*********************************"); diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java index ac4f60a8c..83b7e9970 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/ProcessRepoZip.java @@ -54,8 +54,6 @@ public class ProcessRepoZip extends ParallelTask { JarOutputStream dest = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output))); JarEntry entry; String path; - int size; - byte buffer[] = new byte[4096]; while ((entry = source.getNextJarEntry()) != null) { // Remove the top directory from the path path = entry.getName().substring(entry.getName().indexOf("/") + 1); @@ -68,9 +66,7 @@ public class ProcessRepoZip extends ParallelTask { continue; } dest.putNextEntry(new JarEntry(path)); - while((size = source.read(buffer)) != -1) { - dest.write(buffer, 0, size); - } + Utils.inToOut(source, dest); } source.close(); dest.close(); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index e8a3a81be..22bae6911 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -28,6 +28,9 @@ import com.topjohnwu.magisk.components.SnackbarMaker; import com.topjohnwu.magisk.receivers.DownloadReceiver; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -215,4 +218,13 @@ public class Utils { return null; } } + + public static void inToOut(InputStream in, OutputStream out) throws IOException { + int read; + byte buffer[] = new byte[4096]; + while ((read = in.read(buffer)) > 0) { + out.write(buffer, 0, read); + } + out.flush(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java b/app/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java index 6fc0f3841..9d79113e5 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/ZipUtils.java @@ -16,8 +16,8 @@ import java.util.jar.JarInputStream; public class ZipUtils { // File name in assets - static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem"; - static final String PRIVATE_KEY_NAME = "private.key.pk8"; + public static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem"; + public static final String PRIVATE_KEY_NAME = "private.key.pk8"; static { System.loadLibrary("zipadjust"); @@ -32,7 +32,6 @@ public class ZipUtils { } public static void unzip(InputStream zip, File folder, String path, boolean junkPath) throws Exception { - byte data[] = new byte[4096]; try { JarInputStream zipfile = new JarInputStream(zip); JarEntry entry; @@ -49,13 +48,9 @@ public class ZipUtils { } File dest = new File(folder, name); dest.getParentFile().mkdirs(); - FileOutputStream out = new FileOutputStream(dest); - int count; - while ((count = zipfile.read(data)) != -1) { - out.write(data, 0, count); + try (FileOutputStream out = new FileOutputStream(dest)) { + Utils.inToOut(zipfile, out); } - out.flush(); - out.close(); } } catch(Exception e) { e.printStackTrace(); diff --git a/crypto/src/main/java/com/topjohnwu/crypto/SignBoot.java b/crypto/src/main/java/com/topjohnwu/crypto/SignBoot.java index 50d6909a8..beb434274 100644 --- a/crypto/src/main/java/com/topjohnwu/crypto/SignBoot.java +++ b/crypto/src/main/java/com/topjohnwu/crypto/SignBoot.java @@ -15,8 +15,6 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;