Skip to content

Commit fb288f2

Browse files
committed
Expose the ed25519 API
This adds a low-level APIs to perform computations over the edwards25519 curve, only useful to implement custom constructions. Exposed functions: crypto_ed25519_scalarmult/2, crypto_ed25519_scalarmult_base/1, crypto_ed25519_scalarmult_noclamp/2, crypto_ed25519_scalarmult_base_noclamp/1, crypto_ed25519_add/2, crypto_ed25519_sub/2, crypto_ed25519_is_valid_point/1, crypto_ed25519_scalar_reduce/1, crypto_ed25519_scalar_negate/1, crypto_ed25519_scalar_add/2, crypto_ed25519_scalar_sub/2, crypto_ed25519_scalar_mul/2
1 parent 67fceef commit fb288f2

File tree

6 files changed

+590
-3
lines changed

6 files changed

+590
-3
lines changed

c_src/ed25519.c

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
#include <sodium.h>
2+
#include <string.h>
3+
4+
#include <erl_nif.h>
5+
6+
#include "enacl.h"
7+
#include "ed25519.h"
8+
9+
ERL_NIF_TERM
10+
enacl_crypto_ed25519_is_valid_point(ErlNifEnv *env, int argc,
11+
ERL_NIF_TERM const argv[]) {
12+
ErlNifBinary p;
13+
14+
if ((argc != 1) ||
15+
(!enif_inspect_binary(env, argv[0], &p)) ||
16+
(p.size != crypto_core_ed25519_BYTES)) {
17+
return enif_make_badarg(env);
18+
}
19+
20+
if (1 == crypto_core_ed25519_is_valid_point(p.data)) {
21+
return enif_make_atom(env, "true");
22+
} else {
23+
return enif_make_atom(env, "false");
24+
}
25+
}
26+
27+
ERL_NIF_TERM
28+
enacl_crypto_ed25519_add(ErlNifEnv *env, int argc,
29+
ERL_NIF_TERM const argv[]) {
30+
ERL_NIF_TERM result;
31+
ErlNifBinary p, q, output;
32+
33+
if ((argc != 2) ||
34+
(!enif_inspect_binary(env, argv[0], &p)) ||
35+
(!enif_inspect_binary(env, argv[1], &q)) ||
36+
(p.size != crypto_core_ed25519_BYTES) ||
37+
(q.size != crypto_core_ed25519_BYTES)) {
38+
return enif_make_badarg(env);
39+
}
40+
41+
do {
42+
if (!enif_alloc_binary(crypto_core_ed25519_BYTES, &output)) {
43+
result = enacl_internal_error(env);
44+
continue;
45+
}
46+
47+
if (crypto_core_ed25519_add(output.data, p.data, q.data) != 0) {
48+
enif_release_binary(&output);
49+
result = enacl_error_tuple(env, "ed25519_add_failed");
50+
continue;
51+
}
52+
53+
result = enif_make_binary(env, &output);
54+
} while (0);
55+
56+
return result;
57+
}
58+
59+
ERL_NIF_TERM
60+
enacl_crypto_ed25519_sub(ErlNifEnv *env, int argc,
61+
ERL_NIF_TERM const argv[]) {
62+
ERL_NIF_TERM result;
63+
ErlNifBinary p, q, output;
64+
65+
if ((argc != 2) ||
66+
(!enif_inspect_binary(env, argv[0], &p)) ||
67+
(!enif_inspect_binary(env, argv[1], &q)) ||
68+
(p.size != crypto_core_ed25519_BYTES) ||
69+
(q.size != crypto_core_ed25519_BYTES)) {
70+
return enif_make_badarg(env);
71+
}
72+
73+
do {
74+
if (!enif_alloc_binary(crypto_core_ed25519_BYTES, &output)) {
75+
result = enacl_internal_error(env);
76+
continue;
77+
}
78+
79+
if (crypto_core_ed25519_sub(output.data, p.data, q.data) != 0) {
80+
enif_release_binary(&output);
81+
result = enacl_error_tuple(env, "ed25519_sub_failed");
82+
continue;
83+
}
84+
85+
result = enif_make_binary(env, &output);
86+
} while (0);
87+
88+
return result;
89+
}
90+
91+
ERL_NIF_TERM
92+
enacl_crypto_ed25519_scalarmult(ErlNifEnv *env, int argc,
93+
ERL_NIF_TERM const argv[]) {
94+
ERL_NIF_TERM result;
95+
ErlNifBinary secret, basepoint, output;
96+
uint8_t bp[crypto_scalarmult_ed25519_BYTES];
97+
98+
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &secret)) ||
99+
(!enif_inspect_binary(env, argv[1], &basepoint)) ||
100+
(secret.size != crypto_scalarmult_ed25519_BYTES) ||
101+
(basepoint.size != crypto_scalarmult_ed25519_BYTES)) {
102+
return enif_make_badarg(env);
103+
}
104+
105+
memcpy(bp, basepoint.data, crypto_scalarmult_ed25519_BYTES);
106+
107+
/* Clear the high-bit. Better safe than sorry. */
108+
bp[crypto_scalarmult_curve25519_BYTES - 1] &= 0x7f;
109+
110+
do {
111+
if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) {
112+
result = enacl_internal_error(env);
113+
continue;
114+
}
115+
116+
if (crypto_scalarmult_ed25519(output.data, secret.data, bp) != 0) {
117+
enif_release_binary(&output);
118+
result = enacl_error_tuple(env, "scalarmult_ed25519_failed");
119+
continue;
120+
}
121+
122+
result = enif_make_binary(env, &output);
123+
} while (0);
124+
125+
sodium_memzero(bp, crypto_scalarmult_curve25519_BYTES);
126+
127+
return result;
128+
}
129+
130+
ERL_NIF_TERM
131+
enacl_crypto_ed25519_scalarmult_base(ErlNifEnv *env, int argc,
132+
ERL_NIF_TERM const argv[]) {
133+
ERL_NIF_TERM result;
134+
ErlNifBinary secret, output;
135+
136+
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &secret)) ||
137+
(secret.size != crypto_scalarmult_ed25519_BYTES)) {
138+
return enif_make_badarg(env);
139+
}
140+
141+
do {
142+
if (!enif_alloc_binary(crypto_scalarmult_ed25519_BYTES, &output)) {
143+
result = enacl_internal_error(env);
144+
continue;
145+
}
146+
147+
if (crypto_scalarmult_ed25519_base(output.data, secret.data) != 0) {
148+
enif_release_binary(&output);
149+
result = enacl_error_tuple(env, "scalarmult_ed25519_base_failed");
150+
continue;
151+
}
152+
153+
result = enif_make_binary(env, &output);
154+
} while (0);
155+
156+
return result;
157+
}
158+
159+
ERL_NIF_TERM
160+
enacl_crypto_ed25519_scalarmult_noclamp(ErlNifEnv *env, int argc,
161+
ERL_NIF_TERM const argv[]) {
162+
ERL_NIF_TERM result;
163+
ErlNifBinary secret, basepoint, output;
164+
uint8_t bp[crypto_scalarmult_ed25519_BYTES];
165+
166+
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &secret)) ||
167+
(!enif_inspect_binary(env, argv[1], &basepoint)) ||
168+
(secret.size != crypto_scalarmult_ed25519_BYTES) ||
169+
(basepoint.size != crypto_scalarmult_ed25519_BYTES)) {
170+
return enif_make_badarg(env);
171+
}
172+
173+
memcpy(bp, basepoint.data, crypto_scalarmult_ed25519_BYTES);
174+
175+
/* Clear the high-bit. Better safe than sorry. */
176+
bp[crypto_scalarmult_curve25519_BYTES - 1] &= 0x7f;
177+
178+
do {
179+
if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) {
180+
result = enacl_internal_error(env);
181+
continue;
182+
}
183+
184+
if (crypto_scalarmult_ed25519_noclamp(output.data, secret.data, bp) != 0) {
185+
enif_release_binary(&output);
186+
result = enacl_error_tuple(env, "scalarmult_ed25519_noclamp_failed");
187+
continue;
188+
}
189+
190+
result = enif_make_binary(env, &output);
191+
} while (0);
192+
193+
sodium_memzero(bp, crypto_scalarmult_curve25519_BYTES);
194+
195+
return result;
196+
}
197+
198+
ERL_NIF_TERM
199+
enacl_crypto_ed25519_scalarmult_base_noclamp(ErlNifEnv *env, int argc,
200+
ERL_NIF_TERM const argv[]) {
201+
ERL_NIF_TERM result;
202+
ErlNifBinary secret, output;
203+
204+
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &secret)) ||
205+
(secret.size != crypto_scalarmult_ed25519_BYTES)) {
206+
return enif_make_badarg(env);
207+
}
208+
209+
do {
210+
if (!enif_alloc_binary(crypto_scalarmult_ed25519_BYTES, &output)) {
211+
result = enacl_internal_error(env);
212+
continue;
213+
}
214+
215+
if (crypto_scalarmult_ed25519_base_noclamp(output.data, secret.data) != 0) {
216+
enif_release_binary(&output);
217+
result = enacl_error_tuple(env, "scalarmult_ed25519_base_noclamp_failed");
218+
continue;
219+
}
220+
221+
result = enif_make_binary(env, &output);
222+
} while (0);
223+
224+
return result;
225+
}
226+
227+
ERL_NIF_TERM
228+
enacl_crypto_ed25519_scalar_reduce(ErlNifEnv *env, int argc,
229+
ERL_NIF_TERM const argv[]) {
230+
ERL_NIF_TERM result;
231+
ErlNifBinary scalar, output;
232+
233+
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &scalar)) ||
234+
(scalar.size != crypto_core_ed25519_NONREDUCEDSCALARBYTES)) {
235+
return enif_make_badarg(env);
236+
}
237+
238+
do {
239+
if (!enif_alloc_binary(crypto_core_ed25519_SCALARBYTES, &output)) {
240+
result = enacl_internal_error(env);
241+
continue;
242+
}
243+
244+
crypto_core_ed25519_scalar_reduce(output.data, scalar.data);
245+
result = enif_make_binary(env, &output);
246+
} while (0);
247+
248+
return result;
249+
}
250+
251+
ERL_NIF_TERM
252+
enacl_crypto_ed25519_scalar_negate(ErlNifEnv *env, int argc,
253+
ERL_NIF_TERM const argv[]) {
254+
ERL_NIF_TERM result;
255+
ErlNifBinary scalar, output;
256+
257+
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &scalar)) ||
258+
(scalar.size != crypto_core_ed25519_SCALARBYTES)) {
259+
return enif_make_badarg(env);
260+
}
261+
262+
do {
263+
if (!enif_alloc_binary(crypto_core_ed25519_SCALARBYTES, &output)) {
264+
result = enacl_internal_error(env);
265+
continue;
266+
}
267+
268+
crypto_core_ed25519_scalar_negate(output.data, scalar.data);
269+
result = enif_make_binary(env, &output);
270+
} while (0);
271+
272+
return result;
273+
}
274+
275+
ERL_NIF_TERM
276+
enacl_crypto_ed25519_scalar_add(ErlNifEnv *env, int argc,
277+
ERL_NIF_TERM const argv[]) {
278+
ERL_NIF_TERM result;
279+
ErlNifBinary x, y, output;
280+
281+
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) ||
282+
(!enif_inspect_binary(env, argv[1], &y)) ||
283+
(x.size != crypto_core_ed25519_SCALARBYTES) ||
284+
(y.size != crypto_core_ed25519_SCALARBYTES)) {
285+
return enif_make_badarg(env);
286+
}
287+
288+
do {
289+
if (!enif_alloc_binary(crypto_core_ed25519_SCALARBYTES, &output)) {
290+
result = enacl_internal_error(env);
291+
continue;
292+
}
293+
294+
crypto_core_ed25519_scalar_add(output.data, x.data, y.data);
295+
result = enif_make_binary(env, &output);
296+
} while (0);
297+
298+
return result;
299+
}
300+
301+
ERL_NIF_TERM
302+
enacl_crypto_ed25519_scalar_sub(ErlNifEnv *env, int argc,
303+
ERL_NIF_TERM const argv[]) {
304+
ERL_NIF_TERM result;
305+
ErlNifBinary x, y, output;
306+
307+
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) ||
308+
(!enif_inspect_binary(env, argv[1], &y)) ||
309+
(x.size != crypto_core_ed25519_SCALARBYTES) ||
310+
(y.size != crypto_core_ed25519_SCALARBYTES)) {
311+
return enif_make_badarg(env);
312+
}
313+
314+
do {
315+
if (!enif_alloc_binary(crypto_core_ed25519_SCALARBYTES, &output)) {
316+
result = enacl_internal_error(env);
317+
continue;
318+
}
319+
320+
crypto_core_ed25519_scalar_sub(output.data, x.data, y.data);
321+
result = enif_make_binary(env, &output);
322+
} while (0);
323+
324+
return result;
325+
}
326+
327+
ERL_NIF_TERM
328+
enacl_crypto_ed25519_scalar_mul(ErlNifEnv *env, int argc,
329+
ERL_NIF_TERM const argv[]) {
330+
ERL_NIF_TERM result;
331+
ErlNifBinary x, y, output;
332+
333+
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &x)) ||
334+
(!enif_inspect_binary(env, argv[1], &y)) ||
335+
(x.size != crypto_core_ed25519_SCALARBYTES) ||
336+
(y.size != crypto_core_ed25519_SCALARBYTES)) {
337+
return enif_make_badarg(env);
338+
}
339+
340+
do {
341+
if (!enif_alloc_binary(crypto_core_ed25519_SCALARBYTES, &output)) {
342+
result = enacl_internal_error(env);
343+
continue;
344+
}
345+
346+
crypto_core_ed25519_scalar_mul(output.data, x.data, y.data);
347+
result = enif_make_binary(env, &output);
348+
} while (0);
349+
350+
return result;
351+
}
352+
353+

c_src/ed25519.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef ENACL_ED25519_H
2+
#define ENACL_ED25519_H
3+
4+
#include <erl_nif.h>
5+
6+
ERL_NIF_TERM enacl_crypto_ed25519_scalarmult(ErlNifEnv *env, int argc,
7+
ERL_NIF_TERM const argv[]);
8+
9+
ERL_NIF_TERM enacl_crypto_ed25519_scalarmult_base(ErlNifEnv *env, int argc,
10+
ERL_NIF_TERM const argv[]);
11+
12+
ERL_NIF_TERM enacl_crypto_ed25519_scalarmult_noclamp(
13+
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]);
14+
15+
ERL_NIF_TERM enacl_crypto_ed25519_scalarmult_base_noclamp(
16+
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]);
17+
18+
ERL_NIF_TERM enacl_crypto_ed25519_add(ErlNifEnv *env, int argc,
19+
ERL_NIF_TERM const argv[]);
20+
21+
ERL_NIF_TERM enacl_crypto_ed25519_sub(ErlNifEnv *env, int argc,
22+
ERL_NIF_TERM const argv[]);
23+
24+
ERL_NIF_TERM enacl_crypto_ed25519_is_valid_point(ErlNifEnv *env, int argc,
25+
ERL_NIF_TERM const argv[]);
26+
27+
ERL_NIF_TERM enacl_crypto_ed25519_scalar_reduce(ErlNifEnv *env, int argc,
28+
ERL_NIF_TERM const argv[]);
29+
30+
ERL_NIF_TERM enacl_crypto_ed25519_scalar_negate(ErlNifEnv *env, int argc,
31+
ERL_NIF_TERM const argv[]);
32+
33+
ERL_NIF_TERM enacl_crypto_ed25519_scalar_add(ErlNifEnv *env, int argc,
34+
ERL_NIF_TERM const argv[]);
35+
36+
ERL_NIF_TERM enacl_crypto_ed25519_scalar_sub(ErlNifEnv *env, int argc,
37+
ERL_NIF_TERM const argv[]);
38+
39+
ERL_NIF_TERM enacl_crypto_ed25519_scalar_mul(ErlNifEnv *env, int argc,
40+
ERL_NIF_TERM const argv[]);
41+
#endif

0 commit comments

Comments
 (0)