1 /*
2 Ignores top bit of h.
3 */
4
5 void
fe25519_frombytes(fe25519 h,const unsigned char * s)6 fe25519_frombytes(fe25519 h, const unsigned char *s)
7 {
8 const uint64_t mask = 0x7ffffffffffffULL;
9 uint64_t h0, h1, h2, h3, h4;
10
11 h0 = (LOAD64_LE(s ) ) & mask;
12 h1 = (LOAD64_LE(s + 6) >> 3) & mask;
13 h2 = (LOAD64_LE(s + 12) >> 6) & mask;
14 h3 = (LOAD64_LE(s + 19) >> 1) & mask;
15 h4 = (LOAD64_LE(s + 24) >> 12) & mask;
16
17 h[0] = h0;
18 h[1] = h1;
19 h[2] = h2;
20 h[3] = h3;
21 h[4] = h4;
22 }
23
24 static void
fe25519_reduce(fe25519 h,const fe25519 f)25 fe25519_reduce(fe25519 h, const fe25519 f)
26 {
27 const uint64_t mask = 0x7ffffffffffffULL;
28 uint128_t t[5];
29
30 t[0] = f[0];
31 t[1] = f[1];
32 t[2] = f[2];
33 t[3] = f[3];
34 t[4] = f[4];
35
36 t[1] += t[0] >> 51;
37 t[0] &= mask;
38 t[2] += t[1] >> 51;
39 t[1] &= mask;
40 t[3] += t[2] >> 51;
41 t[2] &= mask;
42 t[4] += t[3] >> 51;
43 t[3] &= mask;
44 t[0] += 19 * (t[4] >> 51);
45 t[4] &= mask;
46
47 t[1] += t[0] >> 51;
48 t[0] &= mask;
49 t[2] += t[1] >> 51;
50 t[1] &= mask;
51 t[3] += t[2] >> 51;
52 t[2] &= mask;
53 t[4] += t[3] >> 51;
54 t[3] &= mask;
55 t[0] += 19 * (t[4] >> 51);
56 t[4] &= mask;
57
58 /* now t is between 0 and 2^255-1, properly carried. */
59 /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
60
61 t[0] += 19ULL;
62
63 t[1] += t[0] >> 51;
64 t[0] &= mask;
65 t[2] += t[1] >> 51;
66 t[1] &= mask;
67 t[3] += t[2] >> 51;
68 t[2] &= mask;
69 t[4] += t[3] >> 51;
70 t[3] &= mask;
71 t[0] += 19ULL * (t[4] >> 51);
72 t[4] &= mask;
73
74 /* now between 19 and 2^255-1 in both cases, and offset by 19. */
75
76 t[0] += 0x8000000000000 - 19ULL;
77 t[1] += 0x8000000000000 - 1ULL;
78 t[2] += 0x8000000000000 - 1ULL;
79 t[3] += 0x8000000000000 - 1ULL;
80 t[4] += 0x8000000000000 - 1ULL;
81
82 /* now between 2^255 and 2^256-20, and offset by 2^255. */
83
84 t[1] += t[0] >> 51;
85 t[0] &= mask;
86 t[2] += t[1] >> 51;
87 t[1] &= mask;
88 t[3] += t[2] >> 51;
89 t[2] &= mask;
90 t[4] += t[3] >> 51;
91 t[3] &= mask;
92 t[4] &= mask;
93
94 h[0] = t[0];
95 h[1] = t[1];
96 h[2] = t[2];
97 h[3] = t[3];
98 h[4] = t[4];
99 }
100
101 void
fe25519_tobytes(unsigned char * s,const fe25519 h)102 fe25519_tobytes(unsigned char *s, const fe25519 h)
103 {
104 fe25519 t;
105 uint64_t t0, t1, t2, t3;
106
107 fe25519_reduce(t, h);
108 t0 = t[0] | (t[1] << 51);
109 t1 = (t[1] >> 13) | (t[2] << 38);
110 t2 = (t[2] >> 26) | (t[3] << 25);
111 t3 = (t[3] >> 39) | (t[4] << 12);
112 STORE64_LE(s + 0, t0);
113 STORE64_LE(s + 8, t1);
114 STORE64_LE(s + 16, t2);
115 STORE64_LE(s + 24, t3);
116 }
117