1 /*
2    This file is adapted from ref10/scalarmult.c:
3    The code for Mongomery ladder is replace by the ladder assembly function;
4    Inversion is done in the same way as amd64-51/.
5    (fe is first converted into fe51 after Mongomery ladder)
6 */
7 
8 #include <stddef.h>
9 
10 #ifdef HAVE_AVX_ASM
11 
12 #include "utils.h"
13 #include "curve25519_sandy2x.h"
14 #include "../scalarmult_curve25519.h"
15 #include "fe.h"
16 #include "fe51.h"
17 #include "ladder.h"
18 #include "ladder_base.h"
19 
20 #define x1 var[0]
21 #define x2 var[1]
22 #define z2 var[2]
23 
24 static int
25 crypto_scalarmult_curve25519_sandy2x(unsigned char *q, const unsigned char *n,
26                                      const unsigned char *p)
27 {
28   unsigned char *t = q;
29   fe             var[3];
30   fe51           x_51;
31   fe51           z_51;
32   unsigned int   i;
33 
34   for (i = 0; i < 32; i++) {
35       t[i] = n[i];
36   }
37   t[0] &= 248;
38   t[31] &= 127;
39   t[31] |= 64;
40 
41   fe_frombytes(x1, p);
42 
43   ladder(var, t);
44 
45   z_51.v[0] = (z2[1] << 26) + z2[0];
46   z_51.v[1] = (z2[3] << 26) + z2[2];
47   z_51.v[2] = (z2[5] << 26) + z2[4];
48   z_51.v[3] = (z2[7] << 26) + z2[6];
49   z_51.v[4] = (z2[9] << 26) + z2[8];
50 
51   x_51.v[0] = (x2[1] << 26) + x2[0];
52   x_51.v[1] = (x2[3] << 26) + x2[2];
53   x_51.v[2] = (x2[5] << 26) + x2[4];
54   x_51.v[3] = (x2[7] << 26) + x2[6];
55   x_51.v[4] = (x2[9] << 26) + x2[8];
56 
57   fe51_invert(&z_51, &z_51);
58   fe51_mul(&x_51, &x_51, &z_51);
59   fe51_pack(q, &x_51);
60 
61   return 0;
62 }
63 
64 #undef x2
65 #undef z2
66 
67 #define x2 var[0]
68 #define z2 var[1]
69 
70 static int
71 crypto_scalarmult_curve25519_sandy2x_base(unsigned char *q,
72                                           const unsigned char *n)
73 {
74   unsigned char *t = q;
75   fe             var[3];
76   fe51           x_51;
77   fe51           z_51;
78   unsigned int   i;
79 
80   for (i = 0;i < 32; i++) {
81       t[i] = n[i];
82   }
83   t[0] &= 248;
84   t[31] &= 127;
85   t[31] |= 64;
86 
87   ladder_base(var, t);
88 
89   z_51.v[0] = (z2[1] << 26) + z2[0];
90   z_51.v[1] = (z2[3] << 26) + z2[2];
91   z_51.v[2] = (z2[5] << 26) + z2[4];
92   z_51.v[3] = (z2[7] << 26) + z2[6];
93   z_51.v[4] = (z2[9] << 26) + z2[8];
94 
95   x_51.v[0] = (x2[1] << 26) + x2[0];
96   x_51.v[1] = (x2[3] << 26) + x2[2];
97   x_51.v[2] = (x2[5] << 26) + x2[4];
98   x_51.v[3] = (x2[7] << 26) + x2[6];
99   x_51.v[4] = (x2[9] << 26) + x2[8];
100 
101   fe51_invert(&z_51, &z_51);
102   fe51_mul(&x_51, &x_51, &z_51);
103   fe51_pack(q, &x_51);
104 
105   return 0;
106 }
107 
108 struct crypto_scalarmult_curve25519_implementation
109 crypto_scalarmult_curve25519_sandy2x_implementation = {
110     SODIUM_C99(.mult = ) crypto_scalarmult_curve25519_sandy2x,
111     SODIUM_C99(.mult_base = ) crypto_scalarmult_curve25519_sandy2x_base
112 };
113 
114 #endif
115