diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-04-18 21:11:08 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-04-18 21:11:08 +0200 |
commit | 75cfa6370bc902765c26b50bb858c9a5bc1e8e48 (patch) | |
tree | fdadaf6e2736ad79c9f79576bf9a056ea9d0a6f5 /src/util/crypto_ecc_dlog.c | |
parent | 5ec7af75ea9f8ed86cf28a8efed9a917345d1681 (diff) | |
download | gnunet-75cfa6370bc902765c26b50bb858c9a5bc1e8e48.tar.gz gnunet-75cfa6370bc902765c26b50bb858c9a5bc1e8e48.zip |
SCALARPRODUCT: migrating logic from libgcrypt to libsodium (#6818).
Diffstat (limited to 'src/util/crypto_ecc_dlog.c')
-rw-r--r-- | src/util/crypto_ecc_dlog.c | 525 |
1 files changed, 178 insertions, 347 deletions
diff --git a/src/util/crypto_ecc_dlog.c b/src/util/crypto_ecc_dlog.c index 408d64e58..916acd9dd 100644 --- a/src/util/crypto_ecc_dlog.c +++ b/src/util/crypto_ecc_dlog.c | |||
@@ -32,35 +32,6 @@ | |||
32 | 32 | ||
33 | 33 | ||
34 | /** | 34 | /** |
35 | * Name of the curve we are using. Note that we have hard-coded | ||
36 | * structs that use 256 bits, so using a bigger curve will require | ||
37 | * changes that break stuff badly. The name of the curve given here | ||
38 | * must be agreed by all peers and be supported by libgcrypt. | ||
39 | */ | ||
40 | #define CURVE "Ed25519" | ||
41 | |||
42 | |||
43 | /** | ||
44 | * | ||
45 | */ | ||
46 | static void | ||
47 | extract_pk (gcry_mpi_point_t pt, | ||
48 | gcry_ctx_t ctx, | ||
49 | struct GNUNET_PeerIdentity *pid) | ||
50 | { | ||
51 | gcry_mpi_t q_y; | ||
52 | |||
53 | GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", pt, ctx)); | ||
54 | q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); | ||
55 | GNUNET_assert (q_y); | ||
56 | GNUNET_CRYPTO_mpi_print_unsigned (pid->public_key.q_y, | ||
57 | sizeof(pid->public_key.q_y), | ||
58 | q_y); | ||
59 | gcry_mpi_release (q_y); | ||
60 | } | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Internal structure used to cache pre-calculated values for DLOG calculation. | 35 | * Internal structure used to cache pre-calculated values for DLOG calculation. |
65 | */ | 36 | */ |
66 | struct GNUNET_CRYPTO_EccDlogContext | 37 | struct GNUNET_CRYPTO_EccDlogContext |
@@ -90,160 +61,105 @@ struct GNUNET_CRYPTO_EccDlogContext | |||
90 | }; | 61 | }; |
91 | 62 | ||
92 | 63 | ||
93 | /** | ||
94 | * Convert point value to binary representation. | ||
95 | * | ||
96 | * @param edc calculation context for ECC operations | ||
97 | * @param point computational point representation | ||
98 | * @param[out] bin binary point representation | ||
99 | */ | ||
100 | void | ||
101 | GNUNET_CRYPTO_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
102 | gcry_mpi_point_t point, | ||
103 | struct GNUNET_CRYPTO_EccPoint *bin) | ||
104 | { | ||
105 | gcry_mpi_t q_y; | ||
106 | |||
107 | GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", point, edc->ctx)); | ||
108 | q_y = gcry_mpi_ec_get_mpi ("q@eddsa", edc->ctx, 0); | ||
109 | GNUNET_assert (q_y); | ||
110 | GNUNET_CRYPTO_mpi_print_unsigned (bin->q_y, | ||
111 | sizeof(bin->q_y), | ||
112 | q_y); | ||
113 | gcry_mpi_release (q_y); | ||
114 | } | ||
115 | |||
116 | |||
117 | /** | ||
118 | * Convert binary representation of a point to computational representation. | ||
119 | * | ||
120 | * @param edc calculation context for ECC operations | ||
121 | * @param bin binary point representation | ||
122 | * @return computational representation | ||
123 | */ | ||
124 | gcry_mpi_point_t | ||
125 | GNUNET_CRYPTO_ecc_bin_to_point (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
126 | const struct GNUNET_CRYPTO_EccPoint *bin) | ||
127 | { | ||
128 | gcry_sexp_t pub_sexpr; | ||
129 | gcry_ctx_t ctx; | ||
130 | gcry_mpi_point_t q; | ||
131 | |||
132 | (void) edc; | ||
133 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, | ||
134 | "(public-key(ecc(curve " CURVE ")(q %b)))", | ||
135 | (int) sizeof(bin->q_y), | ||
136 | bin->q_y)) | ||
137 | { | ||
138 | GNUNET_break (0); | ||
139 | return NULL; | ||
140 | } | ||
141 | GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL)); | ||
142 | gcry_sexp_release (pub_sexpr); | ||
143 | q = gcry_mpi_ec_get_point ("q", ctx, 0); | ||
144 | gcry_ctx_release (ctx); | ||
145 | return q; | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Do pre-calculation for ECC discrete logarithm for small factors. | ||
151 | * | ||
152 | * @param max maximum value the factor can be | ||
153 | * @param mem memory to use (should be smaller than @a max), must not be zero. | ||
154 | * @return NULL on error | ||
155 | */ | ||
156 | struct GNUNET_CRYPTO_EccDlogContext * | 64 | struct GNUNET_CRYPTO_EccDlogContext * |
157 | GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, | 65 | GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, |
158 | unsigned int mem) | 66 | unsigned int mem) |
159 | { | 67 | { |
160 | struct GNUNET_CRYPTO_EccDlogContext *edc; | 68 | struct GNUNET_CRYPTO_EccDlogContext *edc; |
161 | unsigned int K = ((max + (mem - 1)) / mem); | 69 | int K = ((max + (mem - 1)) / mem); |
162 | gcry_mpi_point_t g; | ||
163 | struct GNUNET_PeerIdentity key; | ||
164 | gcry_mpi_point_t gKi; | ||
165 | gcry_mpi_t fact; | ||
166 | gcry_mpi_t n; | ||
167 | unsigned int i; | ||
168 | 70 | ||
169 | GNUNET_assert (max < INT32_MAX); | 71 | GNUNET_assert (max < INT32_MAX); |
170 | edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); | 72 | edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); |
171 | edc->max = max; | 73 | edc->max = max; |
172 | edc->mem = mem; | 74 | edc->mem = mem; |
173 | |||
174 | edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, | 75 | edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, |
175 | GNUNET_NO); | 76 | GNUNET_NO); |
176 | 77 | for (int i = -(int) mem; i <= (int) mem; i++) | |
177 | GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, | ||
178 | NULL, | ||
179 | CURVE)); | ||
180 | g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); | ||
181 | GNUNET_assert (NULL != g); | ||
182 | fact = gcry_mpi_new (0); | ||
183 | gKi = gcry_mpi_point_new (0); | ||
184 | for (i = 0; i <= mem; i++) | ||
185 | { | 78 | { |
186 | gcry_mpi_set_ui (fact, i * K); | 79 | struct GNUNET_CRYPTO_EccScalar Ki; |
187 | gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); | 80 | struct GNUNET_PeerIdentity key; |
188 | extract_pk (gKi, edc->ctx, &key); | 81 | |
82 | GNUNET_CRYPTO_ecc_scalar_from_int (K * i, | ||
83 | &Ki); | ||
84 | if (0 == i) /* libsodium does not like to multiply with zero */ | ||
85 | GNUNET_assert ( | ||
86 | 0 == | ||
87 | crypto_core_ed25519_sub ((unsigned char *) &key, | ||
88 | (unsigned char *) &key, | ||
89 | (unsigned char *) &key)); | ||
90 | else | ||
91 | GNUNET_assert ( | ||
92 | 0 == | ||
93 | crypto_scalarmult_ed25519_base_noclamp ((unsigned char*) &key, | ||
94 | Ki.v)); | ||
95 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
96 | "K*i: %d (mem=%u, i=%d) => %s\n", | ||
97 | K * i, | ||
98 | mem, | ||
99 | i, | ||
100 | GNUNET_i2s (&key)); | ||
189 | GNUNET_assert (GNUNET_OK == | 101 | GNUNET_assert (GNUNET_OK == |
190 | GNUNET_CONTAINER_multipeermap_put (edc->map, | 102 | GNUNET_CONTAINER_multipeermap_put (edc->map, |
191 | &key, | 103 | &key, |
192 | (void *) (long) i + max, | 104 | (void *) (long) i + max, |
193 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 105 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
194 | } | 106 | } |
195 | /* negative values */ | ||
196 | n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); | ||
197 | for (i = 1; i < mem; i++) | ||
198 | { | ||
199 | gcry_mpi_set_ui (fact, i * K); | ||
200 | gcry_mpi_sub (fact, n, fact); | ||
201 | gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); | ||
202 | extract_pk (gKi, edc->ctx, &key); | ||
203 | GNUNET_assert (GNUNET_OK == | ||
204 | GNUNET_CONTAINER_multipeermap_put (edc->map, | ||
205 | &key, | ||
206 | (void *) (long) max - i, | ||
207 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
208 | } | ||
209 | gcry_mpi_release (fact); | ||
210 | gcry_mpi_release (n); | ||
211 | gcry_mpi_point_release (gKi); | ||
212 | gcry_mpi_point_release (g); | ||
213 | return edc; | 107 | return edc; |
214 | } | 108 | } |
215 | 109 | ||
216 | 110 | ||
217 | /** | ||
218 | * Calculate ECC discrete logarithm for small factors. | ||
219 | * | ||
220 | * @param edc precalculated values, determine range of factors | ||
221 | * @param input point on the curve to factor | ||
222 | * @return INT_MAX if dlog failed, otherwise the factor | ||
223 | */ | ||
224 | int | 111 | int |
225 | GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, | 112 | GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, |
226 | gcry_mpi_point_t input) | 113 | const struct GNUNET_CRYPTO_EccPoint *input) |
227 | { | 114 | { |
228 | unsigned int K = ((edc->max + (edc->mem - 1)) / edc->mem); | 115 | unsigned int K = ((edc->max + (edc->mem - 1)) / edc->mem); |
229 | gcry_mpi_point_t g; | ||
230 | struct GNUNET_PeerIdentity key; | ||
231 | gcry_mpi_point_t q; | ||
232 | unsigned int i; | ||
233 | int res; | 116 | int res; |
234 | void *retp; | 117 | struct GNUNET_CRYPTO_EccPoint g; |
235 | 118 | struct GNUNET_CRYPTO_EccPoint q; | |
236 | g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); | 119 | struct GNUNET_CRYPTO_EccPoint nq; |
237 | GNUNET_assert (NULL != g); | ||
238 | q = gcry_mpi_point_new (0); | ||
239 | 120 | ||
121 | { | ||
122 | struct GNUNET_CRYPTO_EccScalar fact; | ||
123 | |||
124 | memset (&fact, | ||
125 | 0, | ||
126 | sizeof (fact)); | ||
127 | sodium_increment (fact.v, | ||
128 | sizeof (fact.v)); | ||
129 | GNUNET_assert (0 == | ||
130 | crypto_scalarmult_ed25519_base_noclamp (g.v, | ||
131 | fact.v)); | ||
132 | } | ||
133 | /* make compiler happy: initialize q and nq, technically not needed! */ | ||
134 | memset (&q, | ||
135 | 0, | ||
136 | sizeof (q)); | ||
137 | memset (&nq, | ||
138 | 0, | ||
139 | sizeof (nq)); | ||
240 | res = INT_MAX; | 140 | res = INT_MAX; |
241 | for (i = 0; i <= edc->max / edc->mem; i++) | 141 | for (unsigned int i = 0; i <= edc->max / edc->mem; i++) |
242 | { | 142 | { |
143 | struct GNUNET_PeerIdentity key; | ||
144 | void *retp; | ||
145 | |||
146 | GNUNET_assert (sizeof (key) == crypto_scalarmult_BYTES); | ||
243 | if (0 == i) | 147 | if (0 == i) |
244 | extract_pk (input, edc->ctx, &key); | 148 | { |
149 | memcpy (&key, | ||
150 | input, | ||
151 | sizeof (key)); | ||
152 | } | ||
245 | else | 153 | else |
246 | extract_pk (q, edc->ctx, &key); | 154 | { |
155 | memcpy (&key, | ||
156 | &q, | ||
157 | sizeof (key)); | ||
158 | } | ||
159 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
160 | "Trying offset i=%u): %s\n", | ||
161 | i, | ||
162 | GNUNET_i2s (&key)); | ||
247 | retp = GNUNET_CONTAINER_multipeermap_get (edc->map, | 163 | retp = GNUNET_CONTAINER_multipeermap_get (edc->map, |
248 | &key); | 164 | &key); |
249 | if (NULL != retp) | 165 | if (NULL != retp) |
@@ -257,248 +173,163 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, | |||
257 | break; | 173 | break; |
258 | /* q = q + g */ | 174 | /* q = q + g */ |
259 | if (0 == i) | 175 | if (0 == i) |
260 | gcry_mpi_ec_add (q, input, g, edc->ctx); | 176 | { |
177 | GNUNET_assert (0 == | ||
178 | crypto_core_ed25519_add (q.v, | ||
179 | input->v, | ||
180 | g.v)); | ||
181 | } | ||
261 | else | 182 | else |
262 | gcry_mpi_ec_add (q, q, g, edc->ctx); | 183 | { |
184 | GNUNET_assert (0 == | ||
185 | crypto_core_ed25519_add (q.v, | ||
186 | q.v, | ||
187 | g.v)); | ||
188 | } | ||
263 | } | 189 | } |
264 | gcry_mpi_point_release (g); | ||
265 | gcry_mpi_point_release (q); | ||
266 | |||
267 | return res; | 190 | return res; |
268 | } | 191 | } |
269 | 192 | ||
270 | 193 | ||
271 | /** | 194 | void |
272 | * Generate a random value mod n. | 195 | GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccScalar *r) |
273 | * | ||
274 | * @param edc ECC context | ||
275 | * @return random value mod n. | ||
276 | */ | ||
277 | gcry_mpi_t | ||
278 | GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc) | ||
279 | { | 196 | { |
280 | gcry_mpi_t n; | 197 | crypto_core_ed25519_scalar_random (r->v); |
281 | unsigned int highbit; | ||
282 | gcry_mpi_t r; | ||
283 | |||
284 | n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); | ||
285 | |||
286 | /* check public key for number of bits, bail out if key is all zeros */ | ||
287 | highbit = 256; /* Curve25519 */ | ||
288 | while ((! gcry_mpi_test_bit (n, highbit)) && | ||
289 | (0 != highbit)) | ||
290 | highbit--; | ||
291 | GNUNET_assert (0 != highbit); | ||
292 | /* generate fact < n (without bias) */ | ||
293 | GNUNET_assert (NULL != (r = gcry_mpi_new (0))); | ||
294 | do | ||
295 | { | ||
296 | gcry_mpi_randomize (r, | ||
297 | highbit + 1, | ||
298 | GCRY_STRONG_RANDOM); | ||
299 | } | ||
300 | while (gcry_mpi_cmp (r, n) >= 0); | ||
301 | gcry_mpi_release (n); | ||
302 | return r; | ||
303 | } | 198 | } |
304 | 199 | ||
305 | 200 | ||
306 | /** | ||
307 | * Release precalculated values. | ||
308 | * | ||
309 | * @param edc dlog context | ||
310 | */ | ||
311 | void | 201 | void |
312 | GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc) | 202 | GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc) |
313 | { | 203 | { |
314 | gcry_ctx_release (edc->ctx); | ||
315 | GNUNET_CONTAINER_multipeermap_destroy (edc->map); | 204 | GNUNET_CONTAINER_multipeermap_destroy (edc->map); |
316 | GNUNET_free (edc); | 205 | GNUNET_free (edc); |
317 | } | 206 | } |
318 | 207 | ||
319 | 208 | ||
320 | /** | 209 | void |
321 | * Multiply the generator g of the elliptic curve by @a val | 210 | GNUNET_CRYPTO_ecc_dexp (int val, |
322 | * to obtain the point on the curve representing @a val. | 211 | struct GNUNET_CRYPTO_EccPoint *r) |
323 | * Afterwards, point addition will correspond to integer | ||
324 | * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to | ||
325 | * convert a point back to an integer (as long as the | ||
326 | * integer is smaller than the MAX of the @a edc context). | ||
327 | * | ||
328 | * @param edc calculation context for ECC operations | ||
329 | * @param val value to encode into a point | ||
330 | * @return representation of the value as an ECC point, | ||
331 | * must be freed using #GNUNET_CRYPTO_ecc_free() | ||
332 | */ | ||
333 | gcry_mpi_point_t | ||
334 | GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
335 | int val) | ||
336 | { | 212 | { |
337 | gcry_mpi_t fact; | 213 | struct GNUNET_CRYPTO_EccScalar fact; |
338 | gcry_mpi_t n; | 214 | |
339 | gcry_mpi_point_t g; | 215 | GNUNET_CRYPTO_ecc_scalar_from_int (val, |
340 | gcry_mpi_point_t r; | 216 | &fact); |
341 | 217 | crypto_scalarmult_ed25519_base_noclamp (r->v, | |
342 | g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); | 218 | fact.v); |
343 | GNUNET_assert (NULL != g); | ||
344 | fact = gcry_mpi_new (0); | ||
345 | if (val < 0) | ||
346 | { | ||
347 | n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); | ||
348 | gcry_mpi_set_ui (fact, -val); | ||
349 | gcry_mpi_sub (fact, n, fact); | ||
350 | gcry_mpi_release (n); | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | gcry_mpi_set_ui (fact, val); | ||
355 | } | ||
356 | r = gcry_mpi_point_new (0); | ||
357 | gcry_mpi_ec_mul (r, fact, g, edc->ctx); | ||
358 | gcry_mpi_release (fact); | ||
359 | gcry_mpi_point_release (g); | ||
360 | return r; | ||
361 | } | 219 | } |
362 | 220 | ||
363 | 221 | ||
364 | /** | 222 | enum GNUNET_GenericReturnValue |
365 | * Multiply the generator g of the elliptic curve by @a val | 223 | GNUNET_CRYPTO_ecc_dexp_mpi (const struct GNUNET_CRYPTO_EccScalar *val, |
366 | * to obtain the point on the curve representing @a val. | 224 | struct GNUNET_CRYPTO_EccPoint *r) |
367 | * | ||
368 | * @param edc calculation context for ECC operations | ||
369 | * @param val (positive) value to encode into a point | ||
370 | * @return representation of the value as an ECC point, | ||
371 | * must be freed using #GNUNET_CRYPTO_ecc_free() | ||
372 | */ | ||
373 | gcry_mpi_point_t | ||
374 | GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
375 | gcry_mpi_t val) | ||
376 | { | 225 | { |
377 | gcry_mpi_point_t g; | 226 | if (0 == |
378 | gcry_mpi_point_t r; | 227 | crypto_scalarmult_ed25519_base_noclamp (r->v, |
379 | 228 | val->v)) | |
380 | g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); | 229 | return GNUNET_OK; |
381 | GNUNET_assert (NULL != g); | 230 | return GNUNET_SYSERR; |
382 | r = gcry_mpi_point_new (0); | ||
383 | gcry_mpi_ec_mul (r, val, g, edc->ctx); | ||
384 | gcry_mpi_point_release (g); | ||
385 | return r; | ||
386 | } | 231 | } |
387 | 232 | ||
388 | 233 | ||
389 | /** | 234 | enum GNUNET_GenericReturnValue |
390 | * Add two points on the elliptic curve. | 235 | GNUNET_CRYPTO_ecc_add (const struct GNUNET_CRYPTO_EccPoint *a, |
391 | * | 236 | const struct GNUNET_CRYPTO_EccPoint *b, |
392 | * @param edc calculation context for ECC operations | 237 | struct GNUNET_CRYPTO_EccPoint *r) |
393 | * @param a some value | ||
394 | * @param b some value | ||
395 | * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free() | ||
396 | */ | ||
397 | gcry_mpi_point_t | ||
398 | GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
399 | gcry_mpi_point_t a, | ||
400 | gcry_mpi_point_t b) | ||
401 | { | 238 | { |
402 | gcry_mpi_point_t r; | 239 | if (0 == |
403 | 240 | crypto_core_ed25519_add (r->v, | |
404 | r = gcry_mpi_point_new (0); | 241 | a->v, |
405 | gcry_mpi_ec_add (r, a, b, edc->ctx); | 242 | b->v)) |
406 | return r; | 243 | return GNUNET_OK; |
244 | return GNUNET_SYSERR; | ||
407 | } | 245 | } |
408 | 246 | ||
409 | 247 | ||
410 | /** | 248 | enum GNUNET_GenericReturnValue |
411 | * Multiply the point @a p on the elliptic curve by @a val. | 249 | GNUNET_CRYPTO_ecc_pmul_mpi (const struct GNUNET_CRYPTO_EccPoint *p, |
412 | * | 250 | const struct GNUNET_CRYPTO_EccScalar *val, |
413 | * @param edc calculation context for ECC operations | 251 | struct GNUNET_CRYPTO_EccPoint *r) |
414 | * @param p point to multiply | ||
415 | * @param val (positive) value to encode into a point | ||
416 | * @return representation of the value as an ECC point, | ||
417 | * must be freed using #GNUNET_CRYPTO_ecc_free() | ||
418 | */ | ||
419 | gcry_mpi_point_t | ||
420 | GNUNET_CRYPTO_ecc_pmul_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
421 | gcry_mpi_point_t p, | ||
422 | gcry_mpi_t val) | ||
423 | { | 252 | { |
424 | gcry_mpi_point_t r; | 253 | if (0 == |
425 | 254 | crypto_scalarmult_ed25519_noclamp (r->v, | |
426 | r = gcry_mpi_point_new (0); | 255 | val->v, |
427 | gcry_mpi_ec_mul (r, val, p, edc->ctx); | 256 | p->v)) |
428 | return r; | 257 | return GNUNET_OK; |
258 | return GNUNET_SYSERR; | ||
429 | } | 259 | } |
430 | 260 | ||
431 | 261 | ||
432 | /** | 262 | enum GNUNET_GenericReturnValue |
433 | * Obtain a random point on the curve and its | 263 | GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccPoint *r, |
434 | * additive inverse. Both returned values | 264 | struct GNUNET_CRYPTO_EccPoint *r_inv) |
435 | * must be freed using #GNUNET_CRYPTO_ecc_free(). | ||
436 | * | ||
437 | * @param edc calculation context for ECC operations | ||
438 | * @param[out] r set to a random point on the curve | ||
439 | * @param[out] r_inv set to the additive inverse of @a r | ||
440 | */ | ||
441 | void | ||
442 | GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, | ||
443 | gcry_mpi_point_t *r, | ||
444 | gcry_mpi_point_t *r_inv) | ||
445 | { | 265 | { |
446 | gcry_mpi_t fact; | 266 | struct GNUNET_CRYPTO_EccScalar s; |
447 | gcry_mpi_t n; | 267 | unsigned char inv_s[crypto_scalarmult_ed25519_SCALARBYTES]; |
448 | gcry_mpi_point_t g; | 268 | |
449 | 269 | GNUNET_CRYPTO_ecc_random_mod_n (&s); | |
450 | fact = GNUNET_CRYPTO_ecc_random_mod_n (edc); | 270 | if (0 != |
451 | 271 | crypto_scalarmult_ed25519_base_noclamp (r->v, | |
452 | /* calculate 'r' */ | 272 | s.v)) |
453 | g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); | 273 | return GNUNET_SYSERR; |
454 | GNUNET_assert (NULL != g); | 274 | crypto_core_ed25519_scalar_negate (inv_s, |
455 | *r = gcry_mpi_point_new (0); | 275 | s.v); |
456 | gcry_mpi_ec_mul (*r, fact, g, edc->ctx); | 276 | if (0 != |
457 | 277 | crypto_scalarmult_ed25519_base_noclamp (r_inv->v, | |
458 | /* calculate 'r_inv' */ | 278 | inv_s)) |
459 | n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); | 279 | return GNUNET_SYSERR; |
460 | gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */ | 280 | return GNUNET_OK; |
461 | *r_inv = gcry_mpi_point_new (0); | ||
462 | gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx); | ||
463 | |||
464 | gcry_mpi_release (n); | ||
465 | gcry_mpi_release (fact); | ||
466 | gcry_mpi_point_release (g); | ||
467 | } | 281 | } |
468 | 282 | ||
469 | 283 | ||
470 | /** | ||
471 | * Obtain a random scalar for point multiplication on the curve and | ||
472 | * its multiplicative inverse. | ||
473 | * | ||
474 | * @param edc calculation context for ECC operations | ||
475 | * @param[out] r set to a random scalar on the curve | ||
476 | * @param[out] r_inv set to the multiplicative inverse of @a r | ||
477 | */ | ||
478 | void | 284 | void |
479 | GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, | 285 | GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccScalar *r, |
480 | gcry_mpi_t *r, | 286 | struct GNUNET_CRYPTO_EccScalar *r_neg) |
481 | gcry_mpi_t *r_inv) | ||
482 | { | 287 | { |
483 | gcry_mpi_t n; | 288 | GNUNET_CRYPTO_ecc_random_mod_n (r); |
484 | 289 | crypto_core_ed25519_scalar_negate (r_neg->v, | |
485 | *r = GNUNET_CRYPTO_ecc_random_mod_n (edc); | 290 | r->v); |
486 | /* r_inv = n - r = - r */ | ||
487 | *r_inv = gcry_mpi_new (0); | ||
488 | n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); | ||
489 | gcry_mpi_sub (*r_inv, n, *r); | ||
490 | } | 291 | } |
491 | 292 | ||
492 | 293 | ||
493 | /** | ||
494 | * Free a point value returned by the API. | ||
495 | * | ||
496 | * @param p point to free | ||
497 | */ | ||
498 | void | 294 | void |
499 | GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p) | 295 | GNUNET_CRYPTO_ecc_scalar_from_int (int64_t val, |
296 | struct GNUNET_CRYPTO_EccScalar *r) | ||
500 | { | 297 | { |
501 | gcry_mpi_point_release (p); | 298 | unsigned char fact[crypto_scalarmult_ed25519_SCALARBYTES]; |
299 | uint64_t valBe; | ||
300 | |||
301 | GNUNET_assert (sizeof (*r) == sizeof (fact)); | ||
302 | if (val < 0) | ||
303 | { | ||
304 | if (INT64_MIN == val) | ||
305 | valBe = GNUNET_htonll ((uint64_t) INT64_MAX); | ||
306 | else | ||
307 | valBe = GNUNET_htonll ((uint64_t) (-val)); | ||
308 | } | ||
309 | else | ||
310 | { | ||
311 | valBe = GNUNET_htonll ((uint64_t) val); | ||
312 | } | ||
313 | memset (fact, | ||
314 | 0, | ||
315 | sizeof (fact)); | ||
316 | for (unsigned int i = 0; i < sizeof (val); i++) | ||
317 | fact[i] = ((unsigned char*) &valBe)[sizeof (val) - 1 - i]; | ||
318 | if (val < 0) | ||
319 | { | ||
320 | if (INT64_MIN == val) | ||
321 | /* See above: fact is one too small, increment now that we can */ | ||
322 | sodium_increment (fact, | ||
323 | sizeof (fact)); | ||
324 | crypto_core_ed25519_scalar_negate (r->v, | ||
325 | fact); | ||
326 | } | ||
327 | else | ||
328 | { | ||
329 | memcpy (r, | ||
330 | fact, | ||
331 | sizeof (fact)); | ||
332 | } | ||
502 | } | 333 | } |
503 | 334 | ||
504 | 335 | ||