| #include "ed25519.h" |
| #include "fe.h" |
| |
| void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) { |
| unsigned char e[32]; |
| unsigned int i; |
| |
| fe x1; |
| fe x2; |
| fe z2; |
| fe x3; |
| fe z3; |
| fe tmp0; |
| fe tmp1; |
| |
| int pos; |
| unsigned int swap; |
| unsigned int b; |
| |
| /* copy the private key and make sure it's valid */ |
| for (i = 0; i < 32; ++i) { |
| e[i] = private_key[i]; |
| } |
| |
| e[0] &= 248; |
| e[31] &= 63; |
| e[31] |= 64; |
| |
| /* unpack the public key and convert edwards to montgomery */ |
| /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */ |
| fe_frombytes(x1, public_key); |
| fe_1(tmp1); |
| fe_add(tmp0, x1, tmp1); |
| fe_sub(tmp1, tmp1, x1); |
| fe_invert(tmp1, tmp1); |
| fe_mul(x1, tmp0, tmp1); |
| |
| fe_1(x2); |
| fe_0(z2); |
| fe_copy(x3, x1); |
| fe_1(z3); |
| |
| swap = 0; |
| for (pos = 254; pos >= 0; --pos) { |
| b = e[pos / 8] >> (pos & 7); |
| b &= 1; |
| swap ^= b; |
| fe_cswap(x2, x3, swap); |
| fe_cswap(z2, z3, swap); |
| swap = b; |
| |
| /* from montgomery.h */ |
| fe_sub(tmp0, x3, z3); |
| fe_sub(tmp1, x2, z2); |
| fe_add(x2, x2, z2); |
| fe_add(z2, x3, z3); |
| fe_mul(z3, tmp0, x2); |
| fe_mul(z2, z2, tmp1); |
| fe_sq(tmp0, tmp1); |
| fe_sq(tmp1, x2); |
| fe_add(x3, z3, z2); |
| fe_sub(z2, z3, z2); |
| fe_mul(x2, tmp1, tmp0); |
| fe_sub(tmp1, tmp1, tmp0); |
| fe_sq(z2, z2); |
| fe_mul121666(z3, tmp1); |
| fe_sq(x3, x3); |
| fe_add(tmp0, tmp0, z3); |
| fe_mul(z3, x1, z2); |
| fe_mul(z2, tmp1, tmp0); |
| } |
| |
| fe_cswap(x2, x3, swap); |
| fe_cswap(z2, z3, swap); |
| |
| fe_invert(z2, z2); |
| fe_mul(x2, x2, z2); |
| fe_tobytes(shared_secret, x2); |
| } |