Monero
Loading...
Searching...
No Matches
amd64.c.inc
Go to the documentation of this file.
1// Copyright (c) 2020, The Monero Project
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification, are
6// permitted provided that the following conditions are met:
7//
8// 1. Redistributions of source code must retain the above copyright notice, this list of
9// conditions and the following disclaimer.
10//
11// 2. Redistributions in binary form must reproduce the above copyright notice, this list
12// of conditions and the following disclaimer in the documentation and/or other
13// materials provided with the distribution.
14//
15// 3. Neither the name of the copyright holder nor the names of its contributors may be
16// used to endorse or promote products derived from this software without specific
17// prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Parts of this file from biench.cr.yp.to/supercop.html (2017-02-25):
30// Daniel J. Bernstein
31// Niels Duif
32// Tanja Lange
33// lead: Peter Schwabe
34// Bo-Yin Yang
35
36#include <string.h>
37#include "ge25519.h"
38
39extern void choose_tp(ge25519_pniels *t, unsigned long long pos, signed long long b, const ge25519_pniels *base_multiples);
40
41/* return 0 on success, -1 otherwise. Taken from
42ed25519/amd64-51-30k/ge25519_unpackneg.c - the negation is removed. */
43static int unpack_vartime(ge25519_p3 *r, const unsigned char p[32])
44{
45 fe25519 t, chk, num, den, den2, den4, den6;
46 unsigned char par = p[31] >> 7;
47
48 fe25519_setint(&r->z,1);
49 fe25519_unpack(&r->y, p);
50 fe25519_square(&num, &r->y); /* x = y^2 */
51 fe25519_mul(&den, &num, &ecd); /* den = dy^2 */
52 fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */
53 fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */
54
55 /* Computation of sqrt(num/den)
56 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8)
57 */
58 fe25519_square(&den2, &den);
59 fe25519_square(&den4, &den2);
60 fe25519_mul(&den6, &den4, &den2);
61 fe25519_mul(&t, &den6, &num);
62 fe25519_mul(&t, &t, &den);
63
64 fe25519_pow2523(&t, &t);
65 /* 2. computation of r->x = t * num * den^3
66 */
67 fe25519_mul(&t, &t, &num);
68 fe25519_mul(&t, &t, &den);
69 fe25519_mul(&t, &t, &den);
70 fe25519_mul(&r->x, &t, &den);
71
72 /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not:
73 */
74 fe25519_square(&chk, &r->x);
75 fe25519_mul(&chk, &chk, &den);
76 if (!fe25519_iseq_vartime(&chk, &num))
77 fe25519_mul(&r->x, &r->x, &sqrtm1);
78
79 /* 4. Now we have one of the two square roots, except if input was not a square
80 */
81 fe25519_square(&chk, &r->x);
82 fe25519_mul(&chk, &chk, &den);
83 if (!fe25519_iseq_vartime(&chk, &num))
84 return -1;
85
86 /* 5. Choose the desired square root according to parity:
87 */
88 if(fe25519_getparity(&r->x) == (1-par)) // only change from original function was `!=` -> `==`
89 fe25519_neg(&r->x, &r->x);
90
91 fe25519_mul(&r->t, &r->x, &r->y);
92 return 0;
93}
94
95static void p3_to_pniels(ge25519_pniels* out, ge25519_p3 const* src)
96{
97 fe25519_sub(&out->ysubx, &src->y, &src->x);
98 fe25519_add(&out->xaddy, &src->x, &src->y);
99 fe25519_mul(&out->t2d, &src->t, &ec2d);
100 out->z = src->z;
101}
102
103static void negate(ge25519* out)
104{
105 fe25519_neg(&out->x, &out->x);
106 fe25519_neg(&out->t, &out->t);
107}
108
109// similar to loops in existing implementation, but uses dynamic table instead of fixed `G`.
110static void scalarmult_p1p1(ge25519_p1p1* r, ge25519_pniels const* base, char const* sec)
111{
112 signed char b[64];
114 ge25519_p3 tp3;
115
116 sc25519 s;
117 memcpy(s.v, sec, sizeof(s));
119
120 // set neutral
121 fe25519_setint(&tp3.x, 0);
122 fe25519_setint(&tp3.y, 1);
123 fe25519_setint(&tp3.t, 0);
124 fe25519_setint(&tp3.z, 1);
125 // end set neutral
126
127 for (int i = 63; /* break below*/ ; --i)
128 {
129 choose_tp(&t, (unsigned long long) 0, (signed long long) b[i], base);
130 ge25519_pnielsadd_p1p1(r, &tp3, &t);
131
132 if (i == 0) break;
133
135
136 ge25519_dbl_p1p1(r,(ge25519_p2 *)&tp3);
137 ge25519_p1p1_to_p2((ge25519_p2 *)&tp3, r);
138 ge25519_dbl_p1p1(r,(ge25519_p2 *)&tp3);
139 ge25519_p1p1_to_p2((ge25519_p2 *)&tp3, r);
140 ge25519_dbl_p1p1(r,(ge25519_p2 *)&tp3);
141 ge25519_p1p1_to_p2((ge25519_p2 *)&tp3, r);
142 ge25519_dbl_p1p1(r,(ge25519_p2 *)&tp3);
143 ge25519_p1p1_to_p3(&tp3, r);
144 }
145}
146
147// _similar_ to ge_scalarmult in src/crypto/crypto-ops.c
148static void base_precomp(ge25519_pniels* base, ge25519_p3 const* r)
149{
150 ge25519_p1p1 tp1p1;
151
152 p3_to_pniels(&base[0], r);
153 for (int i = 0; i < 7; ++i)
154 {
155 ge25519_pnielsadd_p1p1(&tp1p1, r, &base[i]);
156 ge25519_p1p1_to_pniels(&base[i + 1], &tp1p1);
157 }
158}
159
160static int scalarmult(char* out, char const* pub, char const* sec)
161{
162 ge25519 unpacked;
164 ge25519_p1p1 tp1p1;
165 if (unpack_vartime(&unpacked, (unsigned char const*)pub) != 0)
166 return -1;
167
168 base_precomp(base, &unpacked);
169 scalarmult_p1p1(&tp1p1, base, sec);
170 ge25519_p1p1_to_p3(&unpacked, &tp1p1);
171
172 ge25519_pack((unsigned char*)out, &unpacked);
173 return 0;
174}
175
176static int generate_key_derivation(char* out, char const* tx_pub, char const* view_sec)
177{
178 ge25519 unpacked;
180 ge25519_p1p1 tp1p1;
181 if (unpack_vartime(&unpacked, (unsigned char const*)tx_pub) != 0)
182 return -1;
183
184 base_precomp(base, &unpacked);
185 scalarmult_p1p1(&tp1p1, base, view_sec);
186
187 // non-standard, monero specific - guarantees point is in ed25519 group
188 ge25519_p1p1_to_p2((ge25519_p2*)&unpacked, &tp1p1);
189 ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)&unpacked);
190 ge25519_p1p1_to_p2((ge25519_p2 *)&unpacked, &tp1p1);
191 ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)&unpacked);
192 ge25519_p1p1_to_p2((ge25519_p2 *)&unpacked, &tp1p1);
193 ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)&unpacked);
194 ge25519_p1p1_to_p3(&unpacked, &tp1p1);
195
196 ge25519_pack((unsigned char*)out, &unpacked);
197 return 0;
198}
199
200static void generate_subaddress_public_key_base(char* out, ge25519 const* output_pub, char const* special_sec)
201{
202 ge25519 p1;
203 sc25519 p2;
204
205 memcpy(p2.v, special_sec, sizeof(p2.v));
206 ge25519_scalarmult_base(&p1, &p2);
207 negate(&p1); // ge25519_sub is not provided by these libraries
208 ge25519_add(&p1, output_pub, &p1);
209 ge25519_pack((unsigned char*)out, &p1);
210}
211
212static int generate_subaddress_public_key(char* out, char const* output_pub, char const* special_sec)
213{
214 ge25519 p;
215 if (unpack_vartime(&p, (unsigned char const*)output_pub) != 0)
216 return -1;
217
218 generate_subaddress_public_key_base(out, &p, special_sec);
219 return 0;
220}
221
#define s(x, c)
Definition aesb.c:47
#define fe25519_neg
Definition fe25519.h:12
#define fe25519_iseq_vartime
Definition fe25519.h:9
#define fe25519_setint
Definition fe25519.h:11
#define fe25519_square
Definition fe25519.h:18
#define fe25519_sub
Definition fe25519.h:15
#define fe25519_pow2523
Definition fe25519.h:21
#define fe25519_unpack
Definition fe25519.h:6
#define fe25519_getparity
Definition fe25519.h:13
#define fe25519_add
Definition fe25519.h:14
#define fe25519
Definition fe25519.h:4
#define fe25519_mul
Definition fe25519.h:16
#define ge25519_dbl_p1p1
Definition ge25519.h:29
#define ge25519_pnielsadd_p1p1
Definition ge25519.h:34
#define ge25519_pack
Definition ge25519.h:18
#define ge25519_add
Definition ge25519.h:20
#define ge25519_p3
Definition ge25519.h:36
#define ge25519
Definition ge25519.h:15
#define ge25519_scalarmult_base
Definition ge25519.h:24
#define ge25519_p1p1_to_p2
Definition ge25519.h:25
#define ge25519_p1p1_to_pniels
Definition ge25519.h:27
#define ge25519_p1p1_to_p3
Definition ge25519.h:26
static const fe25519 ec2d
Definition ge25519_double_scalarmult.c:14
static const fe25519 ecd
Definition ge25519_scalarmult_base.c:11
#define sc25519_window4
Definition sc25519.h:18
#define sc25519
Definition sc25519.h:4
#define choose_tp
Definition amd64-51-30k.c:48
cryptonote::block b
Definition block.cpp:40
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16
Definition base.py:1
t
Definition console.py:33
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition crypto.h:232
@ out
Definition message_store.h:75
int i
Definition pymoduletest.py:23
Definition sqrtm1.py:1
r
Definition testupnpigd.py:61
Definition ge25519.h:47
Definition ge25519.h:55
Definition ge25519.h:69
unsigned long long v[4]
Definition sc25519.h:26