Eliminate max message size for signatures.

Dynamically allocate working buffers instead.

Closes #3
This commit is contained in:
Moxie Marlinspike 2015-04-30 14:48:19 -07:00
parent c8a1fe0f73
commit 1cde4297b8
9 changed files with 46 additions and 36 deletions

View File

@ -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;
}

View File

@ -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 */

Binary file not shown.

Binary file not shown.

View File

@ -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

View File

@ -4,4 +4,8 @@ public class FakeSecureRandomProvider implements SecureRandomProvider {
public void nextBytes(byte[] output) {
}
public int nextInt(int maxValue) {
return maxValue;
}
}

View File

@ -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 {