#if !defined(ED25519_SUFFIX)
#define ED25519_SUFFIX
#endif
#define ED25519_FN3(fn,suffix) fn##suffix
#define ED25519_FN2(fn,suffix) ED25519_FN3(fn,suffix)
#define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX)
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
#include "ed25519-donna.h"
#include "ed25519_donna_tor.h"
#include "ed25519-randombytes.h"
#include "ed25519-hash.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
typedef unsigned char ed25519_signature[64];
typedef unsigned char ed25519_public_key[32];
typedef unsigned char ed25519_secret_key[32];
static void ed25519_donna_gettweak(unsigned char *out,
const unsigned char *param);
static int ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen,
const ed25519_public_key pk, const ed25519_signature RS);
DONNA_INLINE static void
ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
ed25519_hash(extsk, sk, 32);
extsk[0] &= 248;
extsk[31] &= 127;
extsk[31] |= 64;
}
static void
ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) {
ed25519_hash_context ctx;
ed25519_hash_init(&ctx);
ed25519_hash_update(&ctx, RS, 32);
ed25519_hash_update(&ctx, pk, 32);
ed25519_hash_update(&ctx, m, mlen);
ed25519_hash_final(&ctx, hram);
}
static int
ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) {
ge25519 ALIGN(16) R, A;
hash_512bits hash;
bignum256modm hram, S;
unsigned char checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1;
ed25519_hram(hash, RS, pk, m, mlen);
expand256_modm(hram, hash, 64);
expand256_modm(S, RS + 32, 32);
ge25519_double_scalarmult_vartime(&R, &A, hram, S);
ge25519_pack(checkR, &R);
return ed25519_verify(RS, checkR, 32) ? 0 : -1;
}
#include "ed25519-donna-batchverify.h"
void
ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) {
curved25519_key ec;
bignum256modm s;
bignum25519 ALIGN(16) yplusz, zminusy;
ge25519 ALIGN(16) p;
size_t i;
for (i = 0; i < 32; i++) ec[i] = e[i];
ec[0] &= 248;
ec[31] &= 127;
ec[31] |= 64;
expand_raw256_modm(s, ec);
ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
curve25519_add(yplusz, p.y, p.z);
curve25519_sub(zminusy, p.z, p.y);
curve25519_recip(zminusy, zminusy);
curve25519_mul(yplusz, yplusz, zminusy);
curve25519_contract(pk, yplusz);
}
int
ed25519_donna_seckey(unsigned char *sk)
{
ed25519_secret_key seed;
crypto_strongest_rand(seed, 32);
ed25519_extsk(sk, seed);
memwipe(seed, 0, sizeof(seed));
return 0;
}
int
ed25519_donna_seckey_expand(unsigned char *sk, const unsigned char *skseed)
{
ed25519_extsk(sk, skseed);
return 0;
}
int
ed25519_donna_pubkey(unsigned char *pk, const unsigned char *sk)
{
bignum256modm a = {0};
ge25519 ALIGN(16) A = {{0}, {0}, {0}, {0}};
expand256_modm(a, sk, 32);
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
ge25519_pack(pk, &A);
return 0;
}
int
ed25519_donna_keygen(unsigned char *pk, unsigned char *sk)
{
int ok;
ok = ed25519_donna_seckey(sk);
ed25519_donna_pubkey(pk, sk);
return ok;
}
int
ed25519_donna_open(const unsigned char *signature, const unsigned char *m,
size_t mlen, const unsigned char *pk)
{
return ED25519_FN(ed25519_sign_open)(m, mlen, pk, signature);
}
int
ed25519_donna_sign(unsigned char *sig, const unsigned char *m, size_t mlen,
const unsigned char *sk, const unsigned char *pk)
{
ed25519_hash_context ctx;
bignum256modm r = {0}, S, a;
ge25519 ALIGN(16) R = {{0}, {0}, {0}, {0}};
hash_512bits hashr, hram;
ed25519_hash_init(&ctx);
ed25519_hash_update(&ctx, sk + 32, 32);
ed25519_hash_update(&ctx, m, mlen);
ed25519_hash_final(&ctx, hashr);
expand256_modm(r, hashr, 64);
ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
ge25519_pack(sig, &R);
ed25519_hram(hram, sig, pk, m, mlen);
expand256_modm(S, hram, 64);
expand256_modm(a, sk, 32);
mul256_modm(S, S, a);
add256_modm(S, S, r);
contract256_modm(sig + 32, S);
return 0;
}
static void
ed25519_donna_gettweak(unsigned char *out, const unsigned char *param)
{
memcpy(out, param, 32);
out[0] &= 248;
out[31] &= 63;
out[31] |= 64;
}
int
ed25519_donna_blind_secret_key(unsigned char *out, const unsigned char *inp,
const unsigned char *param)
{
static const char str[] = "Derive temporary signing key hash input";
unsigned char tweak[64];
ed25519_hash_context ctx;
bignum256modm ALIGN(16) sk, t;
ed25519_donna_gettweak(tweak, param);
expand256_modm(t, tweak, 32);
expand256_modm(sk, inp, 32);
mul256_modm(sk, sk, t);
contract256_modm(out, sk);
ed25519_hash_init(&ctx);
ed25519_hash_update(&ctx, (const unsigned char*)str, strlen(str));
ed25519_hash_update(&ctx, inp + 32, 32);
ed25519_hash_final(&ctx, tweak);
memcpy(out + 32, tweak, 32);
memwipe(sk, 0, sizeof(sk));
memwipe(t, 0, sizeof(t));
memwipe(tweak, 0, sizeof(tweak));
return 0;
}
int
ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp,
const unsigned char *param)
{
static const bignum256modm zero = { 0 };
unsigned char tweak[64];
unsigned char pkcopy[32];
ge25519 ALIGN(16) A, Aprime;
bignum256modm ALIGN(16) t;
ed25519_donna_gettweak(tweak, param);
expand256_modm(t, tweak, 32);
memcpy(pkcopy, inp, 32);
pkcopy[31] ^= (1<<7);
if (!ge25519_unpack_negative_vartime(&A, pkcopy)) {
return -1;
}
ge25519_double_scalarmult_vartime(&Aprime, &A, t, zero);
ge25519_pack(out, &Aprime);
memwipe(tweak, 0, sizeof(tweak));
memwipe(pkcopy, 0, sizeof(pkcopy));
memwipe(&A, 0, sizeof(A));
memwipe(&Aprime, 0, sizeof(Aprime));
memwipe(t, 0, sizeof(t));
return 0;
}
int
ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
const unsigned char *inp, int signbit)
{
static const bignum25519 ALIGN(16) one = { 1 };
bignum25519 ALIGN(16) u, uminus1, uplus1, inv_uplus1, y;
curve25519_expand(u, inp);
curve25519_sub(uminus1, u, one);
curve25519_add(uplus1, u, one);
curve25519_recip(inv_uplus1, uplus1);
curve25519_mul(y, uminus1, inv_uplus1);
curve25519_contract(out, y);
out[31] |= (!!signbit) << 7;
return 0;
}
int
ed25519_donna_scalarmult_with_group_order(unsigned char *out,
const unsigned char *pubkey)
{
static const bignum256modm ALIGN(16) zero = { 0 };
unsigned char pkcopy[32];
ge25519 ALIGN(16) Point, Result;
memcpy(pkcopy, pubkey, 32);
pkcopy[31] ^= (1<<7);
if (!ge25519_unpack_negative_vartime(&Point, pkcopy)) {
return -1;
}
ge25519_double_scalarmult_vartime(&Result, &Point, modm_m, zero);
ge25519_pack(out, &Result);
return 0;
}
#include "test-internals.c"