diff --git a/android/jni/ed25519/additions/curve_sigs.c b/android/jni/ed25519/additions/curve_sigs.c index 51f2052..fca6606 100644 --- a/android/jni/ed25519/additions/curve_sigs.c +++ b/android/jni/ed25519/additions/curve_sigs.c @@ -40,10 +40,10 @@ int curve25519_sign(unsigned char* signature_out, { ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */ unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */ - unsigned char sigbuf[MAX_MSG_LEN + 128]; /* working buffer */ + unsigned char *sigbuf; /* working buffer */ unsigned char sign_bit = 0; - if (msg_len > MAX_MSG_LEN) { + if ((sigbuf = malloc(msg_len + 128)) == 0) { memset(signature_out, 0, 64); return -1; } @@ -61,6 +61,8 @@ int curve25519_sign(unsigned char* signature_out, /* Encode the sign bit into signature (in unused high bit of S) */ signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ signature_out[63] |= sign_bit; + + free(sigbuf); return 0; } @@ -73,11 +75,18 @@ int curve25519_verify(const unsigned char* signature, fe ed_y; unsigned char ed_pubkey[32]; unsigned long long some_retval; - unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */ - unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */ + unsigned char *verifybuf = NULL; /* working buffer */ + unsigned char *verifybuf2 = NULL; /* working buffer #2 */ + int result; - if (msg_len > MAX_MSG_LEN) { - return -1; + if ((verifybuf = malloc(msg_len + 64)) == 0) { + result = -1; + goto err; + } + + if ((verifybuf2 = malloc(msg_len + 64)) == 0) { + result = -1; + goto err; } /* Convert the Curve25519 public key into an Ed25519 public key. In @@ -112,5 +121,17 @@ int curve25519_verify(const unsigned char* signature, /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets replaced with pubkey for hashing, then the whole thing gets zeroized (if bad sig), or contains a copy of msg (good sig) */ - return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey); + result = crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey); + + err: + + if (verifybuf != NULL) { + free(verifybuf); + } + + if (verifybuf2 != NULL) { + free(verifybuf2); + } + + return result; } diff --git a/android/jni/ed25519/additions/curve_sigs.h b/android/jni/ed25519/additions/curve_sigs.h index cc46247..b3dbad0 100644 --- a/android/jni/ed25519/additions/curve_sigs.h +++ b/android/jni/ed25519/additions/curve_sigs.h @@ -2,8 +2,6 @@ #ifndef __CURVE_SIGS_H__ #define __CURVE_SIGS_H__ -#define MAX_MSG_LEN 256 - void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */ const unsigned char* curve25519_privkey_in); /* 32 bytes */ diff --git a/android/libs/armeabi-v7a/libcurve25519.so b/android/libs/armeabi-v7a/libcurve25519.so index 09073d9..4e33854 100755 Binary files a/android/libs/armeabi-v7a/libcurve25519.so and b/android/libs/armeabi-v7a/libcurve25519.so differ diff --git a/android/libs/armeabi/libcurve25519.so b/android/libs/armeabi/libcurve25519.so index b9364f2..b26b8a9 100755 Binary files a/android/libs/armeabi/libcurve25519.so and b/android/libs/armeabi/libcurve25519.so differ diff --git a/android/libs/mips/libcurve25519.so b/android/libs/mips/libcurve25519.so index 6662a5a..de76f99 100755 Binary files a/android/libs/mips/libcurve25519.so and b/android/libs/mips/libcurve25519.so differ diff --git a/android/libs/x86/libcurve25519.so b/android/libs/x86/libcurve25519.so index ff5b63e..037aec5 100755 Binary files a/android/libs/x86/libcurve25519.so and b/android/libs/x86/libcurve25519.so differ diff --git a/common/src/main/java/org/whispersystems/curve25519/java/curve_sigs.java b/common/src/main/java/org/whispersystems/curve25519/java/curve_sigs.java index 715e43e..4650e92 100644 --- a/common/src/main/java/org/whispersystems/curve25519/java/curve_sigs.java +++ b/common/src/main/java/org/whispersystems/curve25519/java/curve_sigs.java @@ -2,8 +2,6 @@ package org.whispersystems.curve25519.java; public class curve_sigs { - public static int MAX_MSG_LEN = 256; - public static void curve25519_keygen(byte[] curve25519_pubkey_out, byte[] curve25519_privkey_in) { @@ -39,19 +37,14 @@ public class curve_sigs { public static int curve25519_sign(Sha512 sha512provider, byte[] signature_out, byte[] curve25519_privkey, - byte[] msg, long msg_len, + byte[] msg, int msg_len, byte[] random) { ge_p3 ed_pubkey_point = new ge_p3(); /* Ed25519 pubkey point */ byte[] ed_pubkey = new byte[32]; /* Ed25519 encoded pubkey */ - byte[] sigbuf = new byte[MAX_MSG_LEN + 128]; /* working buffer */ + byte[] sigbuf = new byte[msg_len + 128]; /* working buffer */ byte sign_bit = 0; - if (msg_len > MAX_MSG_LEN) { - Arrays.fill(signature_out, (byte)0); - return -1; - } - /* Convert the Curve25519 privkey to an Ed25519 public key */ ge_scalarmult_base.ge_scalarmult_base(ed_pubkey_point, curve25519_privkey); ge_p3_tobytes.ge_p3_tobytes(ed_pubkey, ed_pubkey_point); @@ -70,7 +63,7 @@ public class curve_sigs { public static int curve25519_verify(Sha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, - byte[] msg, long msg_len) + byte[] msg, int msg_len) { int[] mont_x = new int[10]; int[] mont_x_minus_one = new int[10]; @@ -80,12 +73,8 @@ public class curve_sigs { int[] ed_y = new int[10]; byte[] ed_pubkey = new byte[32]; long some_retval = 0; - byte[] verifybuf = new byte[MAX_MSG_LEN + 64]; /* working buffer */ - byte[] verifybuf2 = new byte[MAX_MSG_LEN + 64]; /* working buffer #2 */ - - if (msg_len > MAX_MSG_LEN) { - return -1; - } + byte[] verifybuf = new byte[msg_len + 64]; /* working buffer */ + byte[] verifybuf2 = new byte[msg_len + 64]; /* working buffer #2 */ /* Convert the Curve25519 public key into an Ed25519 public key. In particular, convert Curve25519's "montgomery" x-coordinate into an diff --git a/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java b/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java index 8a97504..9316b62 100644 --- a/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java +++ b/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java @@ -4,4 +4,8 @@ public class FakeSecureRandomProvider implements SecureRandomProvider { public void nextBytes(byte[] output) { } + + public int nextInt(int maxValue) { + return maxValue; + } } diff --git a/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java b/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java index ac93b0e..e2286ba 100644 --- a/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java +++ b/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java @@ -130,18 +130,16 @@ public abstract class Curve25519Test extends TestCase { } } - public void testSignatureOverflow() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException { - Curve25519KeyPair keys = getInstance().generateKeyPair(); - byte[] message = new byte[4096]; + public void testLargeSignatures() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException { + Curve25519KeyPair keys = getInstance().generateKeyPair(); + byte[] message = new byte[1024 * 1024]; + byte[] signature = getInstance().calculateSignature(keys.getPrivateKey(), message); - try { - byte[] signature = getInstance().calculateSignature(keys.getPrivateKey(), message); - throw new InvalidKeyException("Should have asserted!"); - } catch (AssertionError e) { - // Success! - } catch (IllegalArgumentException iae) { - // Success ! - } + assertTrue(getInstance().verifySignature(keys.getPublicKey(), message, signature)); + + signature[0] ^= 0x01; + + assertFalse(getInstance().verifySignature(keys.getPublicKey(), message, signature)); } protected Curve25519 getInstance() throws NoSuchProviderException {