From 62c9f8bdcfca73632839aaa73bd100b4b6f3e377 Mon Sep 17 00:00:00 2001 From: StevenWdV Date: Wed, 9 Feb 2022 00:40:38 +0100 Subject: Fix Android wrapper --- .../src/main/java/org/eduvpn/common/Discovery.java | 80 ++++++++++++++++++++++ .../eduvpn/common/InvalidSignatureException.java | 8 +++ .../InvalidSignatureUnknownKeyException.java | 8 +++ .../eduvpn/common/SignatureTooOldException.java | 8 +++ .../org/eduvpn/common/UnknownVerifyException.java | 9 +++ .../java/org/eduvpn/common/VerifyException.java | 8 +++ 6 files changed, 121 insertions(+) create mode 100644 wrappers/java-android/lib/src/main/java/org/eduvpn/common/Discovery.java create mode 100644 wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureException.java create mode 100644 wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureUnknownKeyException.java create mode 100644 wrappers/java-android/lib/src/main/java/org/eduvpn/common/SignatureTooOldException.java create mode 100644 wrappers/java-android/lib/src/main/java/org/eduvpn/common/UnknownVerifyException.java create mode 100644 wrappers/java-android/lib/src/main/java/org/eduvpn/common/VerifyException.java (limited to 'wrappers/java-android/lib') diff --git a/wrappers/java-android/lib/src/main/java/org/eduvpn/common/Discovery.java b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/Discovery.java new file mode 100644 index 0000000..dfeef71 --- /dev/null +++ b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/Discovery.java @@ -0,0 +1,80 @@ +package org.eduvpn.common; + +import com.sun.jna.*; + +import java.nio.charset.StandardCharsets; + +public final class Discovery { + private static final String LIB_NAME = "eduvpn_common"; + private static final NativeApi discovery = Native.load(LIB_NAME, NativeApi.class); + + /** + * Verifies the signature on the JSON server_list.json/organization_list.json file. + * If the function returns, the signature is valid for the given file type. + * + * @param signature .minisig signature file contents. + * @param signedJson Signed .json file contents. + * @param expectedFileName The file type to be verified, one of {@code "server_list.json"} or {@code "organization_list.json"}. + * @param minSignTime Minimum time for signature (UNIX timestamp, seconds). Should be set to at least the time of the previous signature. + * @throws IllegalArgumentException If {@code expectedFileName} is not one of the allowed values or one of the parameters is empty. + * @throws VerifyException If signature verification fails. + */ + public static void verify(byte[] signature, byte[] signedJson, String expectedFileName, long minSignTime) throws VerifyException { + byte err = discovery.Verify(NativeApi.GoSlice.fromArray(signature), NativeApi.GoSlice.fromArray(signedJson), + NativeApi.GoSlice.fromString(expectedFileName), minSignTime); + + switch (err) { + case 0: + return; + case 1: + throw new IllegalArgumentException("unknown expected file name"); + case 2: + throw new InvalidSignatureException(); + case 3: + throw new InvalidSignatureUnknownKeyException(); + case 4: + throw new SignatureTooOldException(); + default: + throw new UnknownVerifyException(err); + } + } + + /** Use for testing only, see Go documentation. */ + /*package-private*/ + static void insecureTestingSetExtraKey(String keyString) { + discovery.InsecureTestingSetExtraKey(NativeApi.GoSlice.fromArray(keyString.getBytes(StandardCharsets.UTF_8))); + } + + private interface NativeApi extends Library { + // C-compatible structure + @Structure.FieldOrder({"data", "len", "cap"}) + class GoSlice extends Structure implements Structure.ByValue { + public Pointer data; + public long len, cap; + + public GoSlice(Pointer data, long len, long cap) { + this.data = data; + this.len = len; + this.cap = cap; + } + + public static GoSlice fromArray(byte[] bytes) { + Memory memory = new Memory(bytes.length); + memory.write(0, bytes, 0, bytes.length); + return new GoSlice(memory, bytes.length, bytes.length); + } + + /** From string as UTF-8. */ + public static GoSlice fromString(String str) { + return fromArray(str.getBytes(StandardCharsets.UTF_8)); + } + } + + byte Verify(GoSlice signatureFileContent, GoSlice signedJson, GoSlice expectedFileName, long minSignTime); + + void InsecureTestingSetExtraKey(GoSlice keyString); + } + + private Discovery() { + } +} diff --git a/wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureException.java b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureException.java new file mode 100644 index 0000000..b739dd7 --- /dev/null +++ b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureException.java @@ -0,0 +1,8 @@ +package org.eduvpn.common; + +/** Signature is invalid (for the expected file type). */ +public final class InvalidSignatureException extends VerifyException { + public InvalidSignatureException() { + super("invalid signature"); + } +} diff --git a/wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureUnknownKeyException.java b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureUnknownKeyException.java new file mode 100644 index 0000000..6d651e5 --- /dev/null +++ b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/InvalidSignatureUnknownKeyException.java @@ -0,0 +1,8 @@ +package org.eduvpn.common; + +/** Signature was created with an unknown key and has not been verified. */ +public final class InvalidSignatureUnknownKeyException extends VerifyException { + public InvalidSignatureUnknownKeyException() { + super("invalid signature (unknown key)"); + } +} diff --git a/wrappers/java-android/lib/src/main/java/org/eduvpn/common/SignatureTooOldException.java b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/SignatureTooOldException.java new file mode 100644 index 0000000..c89136f --- /dev/null +++ b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/SignatureTooOldException.java @@ -0,0 +1,8 @@ +package org.eduvpn.common; + +/** Signature timestamp smaller than specified minimum signing time (rollback). */ +public final class SignatureTooOldException extends VerifyException { + public SignatureTooOldException() { + super("replay of previous signature (rollback)"); + } +} diff --git a/wrappers/java-android/lib/src/main/java/org/eduvpn/common/UnknownVerifyException.java b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/UnknownVerifyException.java new file mode 100644 index 0000000..80b74ea --- /dev/null +++ b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/UnknownVerifyException.java @@ -0,0 +1,9 @@ +package org.eduvpn.common; + +/** Other unknown error. */ +public final class UnknownVerifyException extends VerifyException { + public UnknownVerifyException(byte code) { + super(String.format("unknown verify error (%d)", code)); + assert code != 0; + } +} diff --git a/wrappers/java-android/lib/src/main/java/org/eduvpn/common/VerifyException.java b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/VerifyException.java new file mode 100644 index 0000000..686ea41 --- /dev/null +++ b/wrappers/java-android/lib/src/main/java/org/eduvpn/common/VerifyException.java @@ -0,0 +1,8 @@ +package org.eduvpn.common; + +/** Verification failed, do not trust the file. */ +public abstract class VerifyException extends Exception { + protected VerifyException(String message) { + super(message); + } +} -- cgit v1.2.3