diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-03-09 12:36:47 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-03-09 12:36:47 -0600 |
commit | 2e55e5fd051278a949d698f84580bef12c9324d8 (patch) | |
tree | f3a2f33b3af02d8f72dc03034841835a60d01266 /tunnel/src/main/java/com/wireguard/android/util | |
parent | 40ebf8006e46f8857340648d7cea234ed699aed7 (diff) |
global: format code
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'tunnel/src/main/java/com/wireguard/android/util')
3 files changed, 116 insertions, 112 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java b/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java index 519ad5cf..82e6a096 100644 --- a/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java +++ b/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java @@ -39,15 +39,14 @@ import androidx.annotation.Nullable; @NonNullForAll public class ModuleLoader { - private static final String MODULE_PUBLIC_KEY_BASE64 = "RWRmHuT9PSqtwfsLtEx+QS06BJtLgFYteL9WCNjH7yuyu5Y1DieSN7If"; private static final String MODULE_LIST_URL = "https://download.wireguard.com/android-module/modules.txt.sig"; - private static final String MODULE_URL = "https://download.wireguard.com/android-module/%s"; private static final String MODULE_NAME = "wireguard-%s.ko"; - - private final RootShell rootShell; - private final String userAgent; + private static final String MODULE_PUBLIC_KEY_BASE64 = "RWRmHuT9PSqtwfsLtEx+QS06BJtLgFYteL9WCNjH7yuyu5Y1DieSN7If"; + private static final String MODULE_URL = "https://download.wireguard.com/android-module/%s"; private final File moduleDir; + private final RootShell rootShell; private final File tmpDir; + private final String userAgent; public ModuleLoader(final Context context, final RootShell rootShell, final String userAgent) { moduleDir = new File(context.getCacheDir(), "kmod"); @@ -56,84 +55,17 @@ public class ModuleLoader { this.userAgent = userAgent; } - public boolean moduleMightExist() { - return moduleDir.exists() && moduleDir.isDirectory(); - } - - public void loadModule() throws IOException, RootShellException { - rootShell.run(null, String.format("insmod \"%s/wireguard-$(sha256sum /proc/version|cut -d ' ' -f 1).ko\"", moduleDir.getAbsolutePath())); - } - public static boolean isModuleLoaded() { return new File("/sys/module/wireguard").exists(); } - private static final class Sha256Digest { - private byte[] bytes; - private Sha256Digest(final String hex) { - if (hex.length() != 64) - throw new InvalidParameterException("SHA256 hashes must be 32 bytes long"); - bytes = new byte[32]; - for (int i = 0; i < 32; ++i) - bytes[i] = (byte)Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16); - } - } - - @Nullable - private Map<String, Sha256Digest> verifySignedHashes(final String signifyDigest) { - final byte[] publicKeyBytes = Base64.decode(MODULE_PUBLIC_KEY_BASE64, Base64.DEFAULT); - - if (publicKeyBytes == null || publicKeyBytes.length != 32 + 10 || publicKeyBytes[0] != 'E' || publicKeyBytes[1] != 'd') - return null; - - final String[] lines = signifyDigest.split("\n", 3); - if (lines.length != 3) - return null; - if (!lines[0].startsWith("untrusted comment: ")) - return null; - - final byte[] signatureBytes = Base64.decode(lines[1], Base64.DEFAULT); - if (signatureBytes == null || signatureBytes.length != 64 + 10) - return null; - for (int i = 0; i < 10; ++i) { - if (signatureBytes[i] != publicKeyBytes[i]) - return null; - } - - try { - EdDSAParameterSpec parameterSpec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519); - Signature signature = new EdDSAEngine(MessageDigest.getInstance(parameterSpec.getHashAlgorithm())); - byte[] rawPublicKeyBytes = new byte[32]; - System.arraycopy(publicKeyBytes, 10, rawPublicKeyBytes, 0, 32); - signature.initVerify(new EdDSAPublicKey(new EdDSAPublicKeySpec(rawPublicKeyBytes, parameterSpec))); - signature.update(lines[2].getBytes(StandardCharsets.UTF_8)); - if (!signature.verify(signatureBytes, 10, 64)) - return null; - } catch (final Exception ignored) { - return null; - } - - Map<String, Sha256Digest> hashes = new HashMap<>(); - for (final String line : lines[2].split("\n")) { - final String[] components = line.split(" ", 2); - if (components.length != 2) - return null; - try { - hashes.put(components[1], new Sha256Digest(components[0])); - } catch (final Exception ignored) { - return null; - } - } - return hashes; - } - public Integer download() throws IOException, RootShellException, NoSuchAlgorithmException { final List<String> output = new ArrayList<>(); rootShell.run(output, "sha256sum /proc/version|cut -d ' ' -f 1"); if (output.size() != 1 || output.get(0).length() != 64) throw new InvalidParameterException("Invalid sha256 of /proc/version"); final String moduleName = String.format(MODULE_NAME, output.get(0)); - HttpURLConnection connection = (HttpURLConnection)new URL(MODULE_LIST_URL).openConnection(); + HttpURLConnection connection = (HttpURLConnection) new URL(MODULE_LIST_URL).openConnection(); connection.setRequestProperty("User-Agent", userAgent); connection.connect(); if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) @@ -150,7 +82,7 @@ public class ModuleLoader { throw new InvalidParameterException("The signature did not verify or invalid hash list format"); if (!modules.containsKey(moduleName)) return OsConstants.ENOENT; - connection = (HttpURLConnection)new URL(String.format(MODULE_URL, moduleName)).openConnection(); + connection = (HttpURLConnection) new URL(String.format(MODULE_URL, moduleName)).openConnection(); connection.setRequestProperty("User-Agent", userAgent); connection.connect(); if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) @@ -185,4 +117,72 @@ public class ModuleLoader { } return OsConstants.EXIT_SUCCESS; } + + public void loadModule() throws IOException, RootShellException { + rootShell.run(null, String.format("insmod \"%s/wireguard-$(sha256sum /proc/version|cut -d ' ' -f 1).ko\"", moduleDir.getAbsolutePath())); + } + + public boolean moduleMightExist() { + return moduleDir.exists() && moduleDir.isDirectory(); + } + + @Nullable + private Map<String, Sha256Digest> verifySignedHashes(final String signifyDigest) { + final byte[] publicKeyBytes = Base64.decode(MODULE_PUBLIC_KEY_BASE64, Base64.DEFAULT); + + if (publicKeyBytes == null || publicKeyBytes.length != 32 + 10 || publicKeyBytes[0] != 'E' || publicKeyBytes[1] != 'd') + return null; + + final String[] lines = signifyDigest.split("\n", 3); + if (lines.length != 3) + return null; + if (!lines[0].startsWith("untrusted comment: ")) + return null; + + final byte[] signatureBytes = Base64.decode(lines[1], Base64.DEFAULT); + if (signatureBytes == null || signatureBytes.length != 64 + 10) + return null; + for (int i = 0; i < 10; ++i) { + if (signatureBytes[i] != publicKeyBytes[i]) + return null; + } + + try { + EdDSAParameterSpec parameterSpec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519); + Signature signature = new EdDSAEngine(MessageDigest.getInstance(parameterSpec.getHashAlgorithm())); + byte[] rawPublicKeyBytes = new byte[32]; + System.arraycopy(publicKeyBytes, 10, rawPublicKeyBytes, 0, 32); + signature.initVerify(new EdDSAPublicKey(new EdDSAPublicKeySpec(rawPublicKeyBytes, parameterSpec))); + signature.update(lines[2].getBytes(StandardCharsets.UTF_8)); + if (!signature.verify(signatureBytes, 10, 64)) + return null; + } catch (final Exception ignored) { + return null; + } + + Map<String, Sha256Digest> hashes = new HashMap<>(); + for (final String line : lines[2].split("\n")) { + final String[] components = line.split(" ", 2); + if (components.length != 2) + return null; + try { + hashes.put(components[1], new Sha256Digest(components[0])); + } catch (final Exception ignored) { + return null; + } + } + return hashes; + } + + private static final class Sha256Digest { + private byte[] bytes; + + private Sha256Digest(final String hex) { + if (hex.length() != 64) + throw new InvalidParameterException("SHA256 hashes must be 32 bytes long"); + bytes = new byte[32]; + for (int i = 0; i < 32; ++i) + bytes[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16); + } + } } diff --git a/tunnel/src/main/java/com/wireguard/android/util/RootShell.java b/tunnel/src/main/java/com/wireguard/android/util/RootShell.java index 9f941815..160ba12f 100644 --- a/tunnel/src/main/java/com/wireguard/android/util/RootShell.java +++ b/tunnel/src/main/java/com/wireguard/android/util/RootShell.java @@ -187,28 +187,32 @@ public class RootShell { } public static class RootShellException extends Exception { - public enum Reason { - NO_ROOT_ACCESS, - SHELL_MARKER_COUNT_ERROR, - SHELL_EXIT_STATUS_READ_ERROR, - SHELL_START_ERROR, - CREATE_BIN_DIR_ERROR, - CREATE_TEMP_DIR_ERROR - } - private final Reason reason; private final Object[] format; - public RootShellException(final Reason reason, final Object ...format) { + private final Reason reason; + public RootShellException(final Reason reason, final Object... format) { this.reason = reason; this.format = format; } - public boolean isIORelated() { - return reason != Reason.NO_ROOT_ACCESS; + + public Object[] getFormat() { + return format; } + public Reason getReason() { return reason; } - public Object[] getFormat() { - return format; + + public boolean isIORelated() { + return reason != Reason.NO_ROOT_ACCESS; + } + + public enum Reason { + NO_ROOT_ACCESS, + SHELL_MARKER_COUNT_ERROR, + SHELL_EXIT_STATUS_READ_ERROR, + SHELL_START_ERROR, + CREATE_BIN_DIR_ERROR, + CREATE_TEMP_DIR_ERROR } } } diff --git a/tunnel/src/main/java/com/wireguard/android/util/ToolsInstaller.java b/tunnel/src/main/java/com/wireguard/android/util/ToolsInstaller.java index f12e755f..f3565c1e 100644 --- a/tunnel/src/main/java/com/wireguard/android/util/ToolsInstaller.java +++ b/tunnel/src/main/java/com/wireguard/android/util/ToolsInstaller.java @@ -40,9 +40,9 @@ public final class ToolsInstaller { private static final String TAG = "WireGuard/" + ToolsInstaller.class.getSimpleName(); private final Context context; - private final RootShell rootShell; private final File localBinaryDir; private final Object lock = new Object(); + private final RootShell rootShell; @Nullable private Boolean areToolsAvailable; @Nullable private Boolean installAsMagiskModule; @@ -107,6 +107,29 @@ public final class ToolsInstaller { } } + public boolean extract() throws IOException { + localBinaryDir.mkdirs(); + final File files[] = new File[EXECUTABLES.length]; + final File tempFiles[] = new File[EXECUTABLES.length]; + boolean allExist = true; + for (int i = 0; i < files.length; ++i) { + files[i] = new File(localBinaryDir, EXECUTABLES[i]); + tempFiles[i] = new File(localBinaryDir, EXECUTABLES[i] + ".tmp"); + allExist &= files[i].exists(); + } + if (allExist) + return false; + for (int i = 0; i < files.length; ++i) { + if (!SharedLibraryLoader.extractLibrary(context, EXECUTABLES[i], tempFiles[i])) + throw new FileNotFoundException("Unable to find " + EXECUTABLES[i]); + if (!tempFiles[i].setExecutable(true, false)) + throw new IOException("Unable to mark " + tempFiles[i].getAbsolutePath() + " as executable"); + if (!tempFiles[i].renameTo(files[i])) + throw new IOException("Unable to rename " + tempFiles[i].getAbsolutePath() + " to " + files[i].getAbsolutePath()); + } + return true; + } + public int install() throws RootShellException, IOException { if (!context.getPackageName().startsWith("com.wireguard.")) throw new SecurityException("The tools may only be installed system-wide from the main WireGuard app."); @@ -161,29 +184,6 @@ public final class ToolsInstaller { } } - public boolean extract() throws IOException { - localBinaryDir.mkdirs(); - final File files[] = new File[EXECUTABLES.length]; - final File tempFiles[] = new File[EXECUTABLES.length]; - boolean allExist = true; - for (int i = 0; i < files.length; ++i) { - files[i] = new File(localBinaryDir, EXECUTABLES[i]); - tempFiles[i] = new File(localBinaryDir, EXECUTABLES[i] + ".tmp"); - allExist &= files[i].exists(); - } - if (allExist) - return false; - for (int i = 0; i < files.length; ++i) { - if (!SharedLibraryLoader.extractLibrary(context, EXECUTABLES[i], tempFiles[i])) - throw new FileNotFoundException("Unable to find " + EXECUTABLES[i]); - if (!tempFiles[i].setExecutable(true, false)) - throw new IOException("Unable to mark " + tempFiles[i].getAbsolutePath() + " as executable"); - if (!tempFiles[i].renameTo(files[i])) - throw new IOException("Unable to rename " + tempFiles[i].getAbsolutePath() + " to " + files[i].getAbsolutePath()); - } - return true; - } - private boolean willInstallAsMagiskModule() { synchronized (lock) { if (installAsMagiskModule == null) { |