mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-25 07:48:10 +00:00
148 lines
3.5 KiB
C
148 lines
3.5 KiB
C
/*
|
|
Public domain by Andrew M. <liquidsun@gmail.com>
|
|
|
|
Ed25519 reference implementation using Ed25519-donna
|
|
*/
|
|
|
|
#include "ed25519-donna.h"
|
|
#include "ed25519.h"
|
|
#include "ed25519-hash-custom.h"
|
|
|
|
#include "curve25519-donna-scalarmult-base.h"
|
|
|
|
/*
|
|
Generates a (extsk[0..31]) and aExt (extsk[32..63])
|
|
*/
|
|
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);
|
|
}
|
|
|
|
void
|
|
ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk) {
|
|
bignum256modm a;
|
|
ge25519 ALIGN(16) A;
|
|
hash_512bits extsk;
|
|
|
|
/* A = aB */
|
|
ed25519_extsk(extsk, sk);
|
|
expand256_modm(a, extsk, 32);
|
|
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
|
|
ge25519_pack(pk, &A);
|
|
}
|
|
|
|
void
|
|
ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) {
|
|
ed25519_hash_context ctx;
|
|
bignum256modm r, S, a;
|
|
ge25519 ALIGN(16) R;
|
|
hash_512bits extsk, hashr, hram;
|
|
|
|
ed25519_extsk(extsk, sk);
|
|
|
|
/* r = H(aExt[32..64], m) */
|
|
ed25519_hash_init(&ctx);
|
|
ed25519_hash_update(&ctx, extsk + 32, 32);
|
|
ed25519_hash_update(&ctx, m, mlen);
|
|
ed25519_hash_final(&ctx, hashr);
|
|
expand256_modm(r, hashr, 64);
|
|
|
|
/* R = rB */
|
|
ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
|
|
ge25519_pack(RS, &R);
|
|
|
|
/* S = H(R,A,m).. */
|
|
ed25519_hram(hram, RS, pk, m, mlen);
|
|
expand256_modm(S, hram, 64);
|
|
|
|
/* S = H(R,A,m)a */
|
|
expand256_modm(a, extsk, 32);
|
|
mul256_modm(S, S, a);
|
|
|
|
/* S = (r + H(R,A,m)a) */
|
|
add256_modm(S, S, r);
|
|
|
|
/* S = (r + H(R,A,m)a) mod L */
|
|
contract256_modm(RS + 32, S);
|
|
}
|
|
|
|
int
|
|
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;
|
|
|
|
/* hram = H(R,A,m) */
|
|
ed25519_hram(hash, RS, pk, m, mlen);
|
|
expand256_modm(hram, hash, 64);
|
|
|
|
/* S */
|
|
expand256_modm(S, RS + 32, 32);
|
|
|
|
/* SB - H(R,A,m)A */
|
|
ge25519_double_scalarmult_vartime(&R, &A, hram, S);
|
|
ge25519_pack(checkR, &R);
|
|
|
|
/* check that R = SB - H(R,A,m)A */
|
|
return ed25519_verify(RS, checkR, 32) ? 0 : -1;
|
|
}
|
|
|
|
/*
|
|
Fast Curve25519 basepoint scalar multiplication
|
|
*/
|
|
void
|
|
curve25519_scalarmult_basepoint(curve25519_key pk, const curve25519_key e) {
|
|
curve25519_key ec;
|
|
bignum256modm s;
|
|
bignum25519 ALIGN(16) yplusz, zminusy;
|
|
ge25519 ALIGN(16) p;
|
|
size_t i;
|
|
|
|
/* clamp */
|
|
for (i = 0; i < 32; i++) ec[i] = e[i];
|
|
ec[0] &= 248;
|
|
ec[31] &= 127;
|
|
ec[31] |= 64;
|
|
|
|
expand_raw256_modm(s, ec);
|
|
|
|
/* scalar * basepoint */
|
|
ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
|
|
|
|
/* u = (y + z) / (z - y) */
|
|
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);
|
|
}
|
|
|
|
void
|
|
curve25519_scalarmult(curve25519_key mypublic, const curve25519_key secret, const curve25519_key basepoint) {
|
|
curve25519_key e;
|
|
size_t i;
|
|
|
|
for (i = 0;i < 32;++i) e[i] = secret[i];
|
|
e[0] &= 0xf8;
|
|
e[31] &= 0x7f;
|
|
e[31] |= 0x40;
|
|
curve25519_scalarmult_donna(mypublic, e, basepoint);
|
|
}
|