1 /*
2  Ignores top bit of h.
3  */
4 
5 void
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
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
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