Update boot signing in InstallMagisk

This commit is contained in:
topjohnwu 2017-10-31 16:31:58 +08:00
parent adf930f126
commit fdd700f3e5
7 changed files with 75 additions and 58 deletions

View File

@ -19,15 +19,13 @@ public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
private static final String BUSYBOX_ARM = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-arm"; 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 static final String BUSYBOX_X86 = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-x86";
private File busybox;
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
Context context = MagiskManager.get(); Context context = MagiskManager.get();
busybox = new File(context.getCacheDir(), "busybox"); File busybox = new File(context.getCacheDir(), "busybox");
Utils.removeItem(context.getApplicationInfo().dataDir + "/busybox"); Utils.removeItem(context.getApplicationInfo().dataDir + "/busybox");
try { try (FileOutputStream out = new FileOutputStream(busybox)) {
FileOutputStream out = new FileOutputStream(busybox);
HttpURLConnection conn = WebService.request( HttpURLConnection conn = WebService.request(
Build.SUPPORTED_32_BIT_ABIS[0].contains("x86") ? Build.SUPPORTED_32_BIT_ABIS[0].contains("x86") ?
BUSYBOX_X86 : BUSYBOX_X86 :
@ -36,12 +34,7 @@ public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
); );
if (conn == null) throw new IOException(); if (conn == null) throw new IOException();
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
byte[] buffer = new byte[4096]; Utils.inToOut(bis, out);
int len;
while ((len = bis.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
conn.disconnect(); conn.disconnect();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -64,10 +64,7 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
) { ) {
if (in == null) throw new FileNotFoundException(); if (in == null) throw new FileNotFoundException();
InputStream buf= new BufferedInputStream(in); InputStream buf= new BufferedInputStream(in);
byte buffer[] = new byte[4096]; Utils.inToOut(buf, out);
int length;
while ((length = buf.read(buffer)) > 0)
out.write(buffer, 0, length);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
mList.add("! Invalid Uri"); mList.add("! Invalid Uri");
throw e; throw e;

View File

@ -1,11 +1,13 @@
package com.topjohnwu.magisk.asyncs; package com.topjohnwu.magisk.asyncs;
import android.app.Activity; import android.app.Activity;
import android.content.res.AssetManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.text.TextUtils; import android.text.TextUtils;
import com.topjohnwu.crypto.SignBoot;
import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.container.AdaptiveList; import com.topjohnwu.magisk.container.AdaptiveList;
import com.topjohnwu.magisk.container.TarEntry; import com.topjohnwu.magisk.container.TarEntry;
@ -103,6 +105,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
ZipUtils.unzip(buf, install, "chromeos/", false); ZipUtils.unzip(buf, install, "chromeos/", false);
buf.reset(); buf.reset();
ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true); ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
buf.close();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
mList.add("! Invalid Uri"); mList.add("! Invalid Uri");
throw e; throw e;
@ -111,10 +114,9 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
throw e; throw e;
} }
File boot; File boot = new File(install, "boot.img");
switch (mode) { switch (mode) {
case PATCH_MODE: case PATCH_MODE:
boot = new File(install, "boot.img");
// Copy boot image to local // Copy boot image to local
try ( try (
InputStream in = mm.getContentResolver().openInputStream(mBootImg); InputStream in = mm.getContentResolver().openInputStream(mBootImg);
@ -136,10 +138,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
// Direct copy raw image // Direct copy raw image
source = new BufferedInputStream(in); source = new BufferedInputStream(in);
} }
byte buffer[] = new byte[1024]; Utils.inToOut(source, out);
int length;
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
mList.add("! Invalid Uri"); mList.add("! Invalid Uri");
throw e; throw e;
@ -147,26 +146,41 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
mList.add("! Copy failed"); mList.add("! Copy failed");
throw e; throw e;
} }
mList.add("- Use boot image: " + boot);
break; break;
case DIRECT_MODE: 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; break;
default: default:
return false; return false;
} }
mList.add("- Use boot image: " + boot); boolean isSigned;
try (InputStream in = new FileInputStream(boot)) {
Shell shell; isSigned = SignBoot.verifySignature(in, null);
if (mode == PATCH_MODE && Shell.rootAccess()) { if (isSigned) {
// Force non-root shell mList.add("- Signed boot image detected");
shell = new Shell("sh"); }
} else { } catch (Exception e) {
shell = Shell.getShell(); mList.add("! Unable to check signature");
throw e;
} }
if (shell == null) // Force non-root shell
return false; Shell shell;
if (Shell.rootAccess())
shell = new Shell("sh");
else
shell = Shell.getShell();
// Patch boot image // Patch boot image
shell.run(mList, shell.run(mList,
@ -180,6 +194,22 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
return false; return false;
File patched_boot = new File(install, "new-boot.img"); 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(""); mList.add("");
switch (mode) { switch (mode) {
case PATCH_MODE: case PATCH_MODE:
@ -190,17 +220,13 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
shell.run_raw(false, "cp -f " + patched_boot + " " + dest); shell.run_raw(false, "cp -f " + patched_boot + " " + dest);
break; break;
case ".img.tar": case ".img.tar":
TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest))); try (
tar.putNextEntry(new TarEntry(patched_boot, "boot.img")); TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
byte buffer[] = new byte[4096]; InputStream in = new FileInputStream(patched_boot)
BufferedInputStream in = new BufferedInputStream(new FileInputStream(patched_boot)); ) {
int len; tar.putNextEntry(new TarEntry(patched_boot, "boot.img"));
while ((len = in.read(buffer)) != -1) { Utils.inToOut(in, tar);
tar.write(buffer, 0, len);
} }
tar.flush();
tar.close();
in.close();
break; break;
} }
mList.add("*********************************"); mList.add("*********************************");

View File

@ -54,8 +54,6 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
JarOutputStream dest = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output))); JarOutputStream dest = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output)));
JarEntry entry; JarEntry entry;
String path; String path;
int size;
byte buffer[] = new byte[4096];
while ((entry = source.getNextJarEntry()) != null) { while ((entry = source.getNextJarEntry()) != null) {
// Remove the top directory from the path // Remove the top directory from the path
path = entry.getName().substring(entry.getName().indexOf("/") + 1); path = entry.getName().substring(entry.getName().indexOf("/") + 1);
@ -68,9 +66,7 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
continue; continue;
} }
dest.putNextEntry(new JarEntry(path)); dest.putNextEntry(new JarEntry(path));
while((size = source.read(buffer)) != -1) { Utils.inToOut(source, dest);
dest.write(buffer, 0, size);
}
} }
source.close(); source.close();
dest.close(); dest.close();

View File

@ -28,6 +28,9 @@ import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.magisk.receivers.DownloadReceiver;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -215,4 +218,13 @@ public class Utils {
return null; 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();
}
} }

View File

@ -16,8 +16,8 @@ import java.util.jar.JarInputStream;
public class ZipUtils { public class ZipUtils {
// File name in assets // File name in assets
static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem"; public static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem";
static final String PRIVATE_KEY_NAME = "private.key.pk8"; public static final String PRIVATE_KEY_NAME = "private.key.pk8";
static { static {
System.loadLibrary("zipadjust"); System.loadLibrary("zipadjust");
@ -32,7 +32,6 @@ public class ZipUtils {
} }
public static void unzip(InputStream zip, File folder, String path, boolean junkPath) throws Exception { public static void unzip(InputStream zip, File folder, String path, boolean junkPath) throws Exception {
byte data[] = new byte[4096];
try { try {
JarInputStream zipfile = new JarInputStream(zip); JarInputStream zipfile = new JarInputStream(zip);
JarEntry entry; JarEntry entry;
@ -49,13 +48,9 @@ public class ZipUtils {
} }
File dest = new File(folder, name); File dest = new File(folder, name);
dest.getParentFile().mkdirs(); dest.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(dest); try (FileOutputStream out = new FileOutputStream(dest)) {
int count; Utils.inToOut(zipfile, out);
while ((count = zipfile.read(data)) != -1) {
out.write(data, 0, count);
} }
out.flush();
out.close();
} }
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -15,8 +15,6 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;