session-android/libaxolotl/jni/ed25519/additions/curve_sigs.c

100 lines
3.6 KiB
C
Raw Normal View History

2014-06-24 19:59:22 +00:00
#include <string.h>
#include "ge.h"
#include "curve_sigs.h"
#include "crypto_sign.h"
void curve25519_keygen(unsigned char* curve25519_pubkey_out,
2014-07-24 18:24:54 +00:00
const unsigned char* curve25519_privkey_in)
2014-06-24 19:59:22 +00:00
{
2014-07-24 18:24:54 +00:00
ge_p3 ed; /* Ed25519 pubkey point */
fe ed_y, ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y;
2014-06-24 19:59:22 +00:00
fe mont_x;
/* Perform a fixed-base multiplication of the Edwards base point,
(which is efficient due to precalculated tables), then convert
to the Curve25519 montgomery-format public key. In particular,
convert Curve25519's "montgomery" x-coordinate into an Ed25519
"edwards" y-coordinate:
2014-07-24 18:24:54 +00:00
mont_x = (ed_y + 1) / (1 - ed_y)
with projective coordinates:
2014-06-24 19:59:22 +00:00
2014-07-24 18:24:54 +00:00
mont_x = (ed_y + ed_z) / (ed_z - ed_y)
*/
2014-06-24 19:59:22 +00:00
2014-07-24 18:24:54 +00:00
ge_scalarmult_base(&ed, curve25519_privkey_in);
fe_add(ed_y_plus_one, ed.Y, ed.Z);
fe_sub(one_minus_ed_y, ed.Z, ed.Y);
2014-06-24 19:59:22 +00:00
fe_invert(inv_one_minus_ed_y, one_minus_ed_y);
fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y);
2014-07-24 18:24:54 +00:00
fe_tobytes(curve25519_pubkey_out, mont_x);
2014-06-24 19:59:22 +00:00
}
void curve25519_sign(unsigned char* signature_out,
2014-07-24 18:24:54 +00:00
const unsigned char* curve25519_privkey,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random)
2014-06-24 19:59:22 +00:00
{
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
2014-07-24 18:24:54 +00:00
unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */
unsigned char sigbuf[msg_len + 128]; /* working buffer */
2014-06-24 19:59:22 +00:00
unsigned char sign_bit = 0;
2014-07-24 18:24:54 +00:00
/* Convert the Curve25519 privkey to an Ed25519 public key */
2014-06-24 19:59:22 +00:00
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
2014-07-24 18:24:54 +00:00
ge_p3_tobytes(ed_pubkey, &ed_pubkey_point);
sign_bit = ed_pubkey[31] & 0x80;
2014-06-24 19:59:22 +00:00
/* Perform an Ed25519 signature with explicit private key */
crypto_sign_modified(sigbuf, msg, msg_len, curve25519_privkey,
2014-07-24 18:24:54 +00:00
ed_pubkey, random);
2014-06-24 19:59:22 +00:00
memmove(signature_out, sigbuf, 64);
/* Encode the sign bit into signature (in unused high bit of S) */
signature_out[63] |= sign_bit;
}
2014-07-24 18:24:54 +00:00
int curve25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
2014-06-24 19:59:22 +00:00
{
fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one;
fe one;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned long long some_retval;
unsigned char verifybuf[msg_len + 64]; /* working buffer */
unsigned char verifybuf2[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
Ed25519 "edwards" y-coordinate:
ed_y = (mont_x - 1) / (mont_x + 1)
Then move the sign bit into the pubkey from the signature.
*/
fe_frombytes(mont_x, curve25519_pubkey);
fe_1(one);
fe_sub(mont_x_minus_one, mont_x, one);
fe_add(mont_x_plus_one, mont_x, one);
fe_invert(inv_mont_x_plus_one, mont_x_plus_one);
fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one);
fe_tobytes(ed_pubkey, ed_y);
/* Copy the sign bit, and remove it from signature */
ed_pubkey[31] |= (signature[63] & 0x80);
memmove(verifybuf, signature, 64);
2014-07-24 18:24:54 +00:00
verifybuf[63] &= 0x7F;
2014-06-24 19:59:22 +00:00
memmove(verifybuf+64, msg, msg_len);
/* Then perform a normal Ed25519 verification, return 0 on success */
2014-07-24 18:24:54 +00:00
/* The below call has a strange API: */
/* verifybuf = R || S || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing, then the whole thing gets zeroized */
2014-06-24 19:59:22 +00:00
return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
}