Use Ed25519 keys.
[tinc] / src / ed25519 / key_exchange.c
1 #include "ed25519.h"
2 #include "fe.h"
3
4 void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
5     unsigned char e[32];
6     unsigned int i;
7     
8     fe x1;
9     fe x2;
10     fe z2;
11     fe x3;
12     fe z3;
13     fe tmp0;
14     fe tmp1;
15
16     int pos;
17     unsigned int swap;
18     unsigned int b;
19
20     /* copy the private key and make sure it's valid */
21     for (i = 0; i < 32; ++i) {
22         e[i] = private_key[i];
23     }
24
25     e[0] &= 248;
26     e[31] &= 63;
27     e[31] |= 64;
28
29     /* unpack the public key and convert edwards to montgomery */
30     /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
31     fe_frombytes(x1, public_key);
32     fe_1(tmp1);
33     fe_add(tmp0, x1, tmp1);
34     fe_sub(tmp1, tmp1, x1);
35     fe_invert(tmp1, tmp1);
36     fe_mul(x1, tmp0, tmp1);
37
38     fe_1(x2);
39     fe_0(z2);
40     fe_copy(x3, x1);
41     fe_1(z3);
42
43     swap = 0;
44     for (pos = 254; pos >= 0; --pos) {
45         b = e[pos / 8] >> (pos & 7);
46         b &= 1;
47         swap ^= b;
48         fe_cswap(x2, x3, swap);
49         fe_cswap(z2, z3, swap);
50         swap = b;
51
52         /* from montgomery.h */
53         fe_sub(tmp0, x3, z3);
54         fe_sub(tmp1, x2, z2);
55         fe_add(x2, x2, z2);
56         fe_add(z2, x3, z3);
57         fe_mul(z3, tmp0, x2);
58         fe_mul(z2, z2, tmp1);
59         fe_sq(tmp0, tmp1);
60         fe_sq(tmp1, x2);
61         fe_add(x3, z3, z2);
62         fe_sub(z2, z3, z2);
63         fe_mul(x2, tmp1, tmp0);
64         fe_sub(tmp1, tmp1, tmp0);
65         fe_sq(z2, z2);
66         fe_mul121666(z3, tmp1);
67         fe_sq(x3, x3);
68         fe_add(tmp0, tmp0, z3);
69         fe_mul(z3, x1, z2);
70         fe_mul(z2, tmp1, tmp0);
71     }
72
73     fe_cswap(x2, x3, swap);
74     fe_cswap(z2, z3, swap);
75
76     fe_invert(z2, z2);
77     fe_mul(x2, x2, z2);
78     fe_tobytes(shared_secret, x2);
79 }