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
24static int
25crypto_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
70static int
71crypto_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
108struct crypto_scalarmult_curve25519_implementation
109crypto_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