aboutsummaryrefslogtreecommitdiff
path: root/crypto.c
diff options
context:
space:
mode:
authorMarkus Teich <markus.teich@stusta.mhn.de>2016-06-16 00:09:29 +0200
committerMarkus Teich <markus.teich@stusta.mhn.de>2016-06-17 10:29:49 +0200
commit761dd37e1f905719df2cd8f4420e4b46da80bffb (patch)
treeb93ec567a19e2407274fc3350ea51186aac8f091 /crypto.c
parent6f3fb463176c04c9a258fce820ec66724a4d13f4 (diff)
downloadlibbrandt-761dd37e1f905719df2cd8f4420e4b46da80bffb.tar.gz
libbrandt-761dd37e1f905719df2cd8f4420e4b46da80bffb.zip
refactor smc and ec crypto functions and ad 0og zkp
Diffstat (limited to 'crypto.c')
-rw-r--r--crypto.c263
1 files changed, 49 insertions, 214 deletions
diff --git a/crypto.c b/crypto.c
index 55ab26a..b4f71e4 100644
--- a/crypto.c
+++ b/crypto.c
@@ -34,8 +34,10 @@ struct brandt_ec_pkey {
34 unsigned char q_y[256 / 8]; 34 unsigned char q_y[256 / 8];
35}; 35};
36 36
37gcry_mpi_point_t ec_gen;
38gcry_ctx_t ec_ctx; 37gcry_ctx_t ec_ctx;
38gcry_mpi_point_t ec_gen;
39gcry_mpi_point_t ec_zero;
40gcry_mpi_t ec_n;
39 41
40/** 42/**
41 * brandt_crypto_init 43 * brandt_crypto_init
@@ -49,10 +51,19 @@ brandt_crypto_init ()
49 51
50 rc = gcry_mpi_ec_new (&ec_ctx, NULL, CURVE); 52 rc = gcry_mpi_ec_new (&ec_ctx, NULL, CURVE);
51 brandt_assert_gpgerr (rc); 53 brandt_assert_gpgerr (rc);
54
52 ec_gen = gcry_mpi_ec_get_point ("g", ec_ctx, 0); 55 ec_gen = gcry_mpi_ec_get_point ("g", ec_ctx, 0);
53 brandt_assert (NULL != ec_gen); 56 brandt_assert (NULL != ec_gen);
57
58 ec_zero = gcry_mpi_point_new (0);
59 brandt_assert (NULL != ec_zero);
60 gcry_mpi_ec_sub (ec_zero, ec_gen, ec_gen, ec_ctx);
61
62 ec_n = gcry_mpi_ec_get_mpi ("n", ec_ctx, 1);
63 brandt_assert (NULL != ec_n);
54} 64}
55 65
66
56/* --- RANDOM --- */ 67/* --- RANDOM --- */
57 68
58void 69void
@@ -64,6 +75,7 @@ brandt_rand_poll ()
64 gcry_fast_random_poll (); 75 gcry_fast_random_poll ();
65} 76}
66 77
78
67/* --- HASHING --- */ 79/* --- HASHING --- */
68 80
69/** 81/**
@@ -79,6 +91,7 @@ brandt_hash (const void *block, size_t size, struct brandt_hash_code *ret)
79 gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size); 91 gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size);
80} 92}
81 93
94
82/* --- MPI --- */ 95/* --- MPI --- */
83 96
84/** 97/**
@@ -101,6 +114,7 @@ adjust (void *buf, size_t size, size_t target)
101 } 114 }
102} 115}
103 116
117
104/** 118/**
105 * Output the given MPI value to the given buffer in 119 * Output the given MPI value to the given buffer in
106 * network byte order. 120 * network byte order.
@@ -141,6 +155,7 @@ brandt_mpi_print_unsigned (void *buf, size_t size, gcry_mpi_t val)
141 } 155 }
142} 156}
143 157
158
144/** 159/**
145 * Convert data buffer into MPI value. 160 * Convert data buffer into MPI value.
146 * The buffer is interpreted as network 161 * The buffer is interpreted as network
@@ -159,6 +174,7 @@ brandt_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size)
159 brandt_assert_gpgerr (rc); 174 brandt_assert_gpgerr (rc);
160} 175}
161 176
177
162//gcry_mpi_point_t 178//gcry_mpi_point_t
163//deserialize_point(const struct brandt_point* data, const int len) 179//deserialize_point(const struct brandt_point* data, const int len)
164//{ 180//{
@@ -185,73 +201,18 @@ brandt_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size)
185/* --- EC --- */ 201/* --- EC --- */
186 202
187/** 203/**
188 * Extract values from an S-expression.
189 *
190 * @param array where to store the result(s)
191 * @param sexp S-expression to parse
192 * @param topname top-level name in the S-expression that is of interest
193 * @param elems names of the elements to extract
194 * @return 0 on success
195 */
196static int
197key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, const char *topname,
198 const char *elems)
199{
200 gcry_sexp_t list;
201 gcry_sexp_t l2;
202 const char *s;
203 unsigned int i;
204 unsigned int idx;
205
206 list = gcry_sexp_find_token (sexp, topname, 0);
207 if (!list)
208 return 1;
209 l2 = gcry_sexp_cadr (list);
210 gcry_sexp_release (list);
211 list = l2;
212 if (!list)
213 return 2;
214 idx = 0;
215 for (s = elems; *s; s++, idx++)
216 {
217 l2 = gcry_sexp_find_token (list, s, 1);
218 if (!l2)
219 {
220 for (i = 0; i < idx; i++)
221 {
222 gcry_free (array[i]);
223 array[i] = NULL;
224 }
225 gcry_sexp_release (list);
226 return 3; /* required parameter not found */
227 }
228 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
229 gcry_sexp_release (l2);
230 if (!array[idx])
231 {
232 for (i = 0; i < idx; i++)
233 {
234 gcry_free (array[i]);
235 array[i] = NULL;
236 }
237 gcry_sexp_release (list);
238 return 4; /* required parameter is invalid */
239 }
240 }
241 gcry_sexp_release (list);
242 return 0;
243}
244
245/**
246 * brandt_ec_skey_create 204 * brandt_ec_skey_create
247 * 205 *
248 * @param[out] skey where to store the generated secret key 206 * @param[out] skey where to store the generated secret key
249 */ 207 */
250void 208void
251brandt_ec_skey_create (gcry_mpi_t *skey) 209brandt_ec_skey_create (gcry_mpi_t skey)
252{ 210{
211 gcry_mpi_t ret;
253 gcry_sexp_t s_keyparam; 212 gcry_sexp_t s_keyparam;
254 gcry_sexp_t priv_sexp; 213 gcry_sexp_t priv_sexp;
214 gcry_sexp_t priv_key;
215 gcry_sexp_t priv_key2;
255 gcry_error_t rc; 216 gcry_error_t rc;
256 217
257 rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" 218 rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")"
@@ -262,24 +223,22 @@ brandt_ec_skey_create (gcry_mpi_t *skey)
262 brandt_assert_gpgerr (rc); 223 brandt_assert_gpgerr (rc);
263 gcry_sexp_release (s_keyparam); 224 gcry_sexp_release (s_keyparam);
264 225
265 rc = key_from_sexp (skey, priv_sexp, "private-key", "d"); 226 priv_key = gcry_sexp_find_token (priv_sexp, "private-key", 11);
266 brandt_assert_gpgerr (rc); 227 brandt_assert (NULL != priv_key);
267
268 gcry_sexp_release (priv_sexp); 228 gcry_sexp_release (priv_sexp);
269}
270 229
271/** 230 priv_key2 = gcry_sexp_find_token (priv_key, "d", 1);
272 * brandt_ec_pkey_compute 231 brandt_assert (NULL != priv_key2);
273 * 232 gcry_sexp_release (priv_key);
274 * @param pkey TODO
275 * @param skey TODO
276 */
277void
278brandt_ec_pkey_compute (gcry_mpi_point_t *pkey, const gcry_mpi_t skey)
279{
280 233
234 ret = gcry_sexp_nth_mpi (priv_key2, 1, GCRYMPI_FMT_USG);
235 brandt_assert (NULL != ret);
236 gcry_sexp_release (priv_key2);
237
238 gcry_mpi_snatch (skey, ret);
281} 239}
282 240
241
283/** 242/**
284 * brandt_ec_keypair_create 243 * brandt_ec_keypair_create
285 * 244 *
@@ -287,33 +246,16 @@ brandt_ec_pkey_compute (gcry_mpi_point_t *pkey, const gcry_mpi_t skey)
287 * @param[out] skey where to store the generated secret key 246 * @param[out] skey where to store the generated secret key
288 */ 247 */
289void 248void
290brandt_ec_keypair_create (gcry_mpi_point_t *pkey, gcry_mpi_t *skey) 249brandt_ec_keypair_create (gcry_mpi_point_t pkey, gcry_mpi_t skey)
291{ 250{
292 gcry_ctx_t ctx; 251 brandt_assert (NULL != pkey);
293 gcry_sexp_t s_keyparam; 252 brandt_assert (NULL != skey);
294 gcry_sexp_t priv_sexp;
295 gcry_error_t rc;
296
297 rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")"
298 "(flags)))");
299 brandt_assert_gpgerr (rc);
300
301 rc = gcry_pk_genkey (&priv_sexp, s_keyparam);
302 brandt_assert_gpgerr (rc);
303 gcry_sexp_release (s_keyparam);
304
305 rc = key_from_sexp (skey, priv_sexp, "private-key", "d");
306 brandt_assert_gpgerr (rc);
307
308 rc = gcry_mpi_ec_new (&ctx, priv_sexp, NULL);
309 brandt_assert_gpgerr (rc);
310 gcry_sexp_release (priv_sexp);
311 253
312 *pkey = gcry_mpi_ec_get_point ("q", ctx, 0); 254 brandt_ec_skey_create (skey);
313 brandt_assert (NULL != *pkey); 255 gcry_mpi_ec_mul (pkey, skey, ec_gen, ec_ctx);
314 gcry_ctx_release (ctx);
315} 256}
316 257
258
317/** 259/**
318 * brandt_ec_keypair_create_base 260 * brandt_ec_keypair_create_base
319 * 261 *
@@ -322,16 +264,19 @@ brandt_ec_keypair_create (gcry_mpi_point_t *pkey, gcry_mpi_t *skey)
322 * @param[in] base which base point should be used to calculate the public key 264 * @param[in] base which base point should be used to calculate the public key
323 */ 265 */
324void 266void
325brandt_ec_keypair_create_base (gcry_mpi_point_t *pkey, gcry_mpi_t *skey, 267brandt_ec_keypair_create_base (gcry_mpi_point_t pkey,
268 gcry_mpi_t skey,
326 const gcry_mpi_point_t base) 269 const gcry_mpi_point_t base)
327{ 270{
271 brandt_assert (NULL != pkey);
272 brandt_assert (NULL != skey);
273 brandt_assert (NULL != base);
274
328 brandt_ec_skey_create (skey); 275 brandt_ec_skey_create (skey);
329 brandt_assert (*skey); 276 gcry_mpi_ec_mul (pkey, skey, base, ec_ctx);
330 *pkey = gcry_mpi_point_new (0);
331 brandt_assert (*pkey);
332 gcry_mpi_ec_mul (*pkey, *skey, base, ec_ctx);
333} 277}
334 278
279
335/** 280/**
336 * brandt_ec_point_cmp compares two curve points 281 * brandt_ec_point_cmp compares two curve points
337 * 282 *
@@ -356,8 +301,8 @@ brandt_ec_point_cmp (const gcry_mpi_point_t a, const gcry_mpi_point_t b)
356 return 1; 301 return 1;
357 } 302 }
358 303
359 if (!gcry_mpi_ec_get_affine (ax, ay, a, ec_ctx) 304 if (!gcry_mpi_ec_get_affine (ax, ay, a, ec_ctx) &&
360 && !gcry_mpi_ec_get_affine (bx, by, b, ec_ctx)) 305 !gcry_mpi_ec_get_affine (bx, by, b, ec_ctx))
361 { 306 {
362 ret = gcry_mpi_cmp (ax, bx) || gcry_mpi_cmp (ay, by); 307 ret = gcry_mpi_cmp (ax, bx) || gcry_mpi_cmp (ay, by);
363 } 308 }
@@ -369,117 +314,6 @@ brandt_ec_point_cmp (const gcry_mpi_point_t a, const gcry_mpi_point_t b)
369 return ret; 314 return ret;
370} 315}
371 316
372/**
373 * Convert the given private key from the network format to the
374 * S-expression that can be used by libgcrypt.
375 *
376 * @param priv private key to decode
377 * @return NULL on error
378 */
379static gcry_sexp_t
380decode_private_ecdhe_key (const struct brandt_ec_skey *priv)
381{
382 gcry_sexp_t result;
383 gcry_error_t rc;
384
385 rc = gcry_sexp_build (&result, NULL,
386 "(private-key(ecc(curve \"" CURVE "\")"
387 "(d %b)))",
388 (int)sizeof (priv->d), priv->d);
389 brandt_assert_gpgerr (rc);
390 return result;
391}
392
393/**
394 * Extract the public key for the given private key.
395 *
396 * @param priv the private key
397 * @param pub where to write the public key
398 */
399void
400brandt_ecdhe_key_get_public (const struct brandt_ec_skey *priv,
401 struct brandt_ec_pkey *pub)
402{
403 gcry_sexp_t sexp;
404 gcry_ctx_t ctx;
405 gcry_mpi_t q;
406 gcry_error_t rc;
407
408 sexp = decode_private_ecdhe_key (priv);
409 brandt_assert (NULL != sexp);
410 rc = gcry_mpi_ec_new (&ctx, sexp, NULL);
411 brandt_assert_gpgerr (rc);
412 gcry_sexp_release (sexp);
413 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
414 brandt_assert (NULL != q);
415 brandt_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
416 gcry_mpi_release (q);
417 gcry_ctx_release (ctx);
418}
419
420/**
421 * Derive key material from a public and a private ECDHE key.
422 *
423 * @param priv private key to use for the ECDH (x)
424 * @param pub public key to use for the ECDH (yG)
425 * @param key_material where to write the key material (xyG)
426 * @return 0 on error, 1 on success
427 */
428int
429brandt_ecdhe (const struct brandt_ec_skey *priv,
430 const struct brandt_ec_pkey *pub,
431 struct brandt_hash_code *key_material)
432{
433 gcry_error_t rc;
434 int rc2;
435 gcry_mpi_point_t result;
436 gcry_mpi_point_t q;
437 gcry_mpi_t d;
438 gcry_ctx_t ctx;
439 gcry_sexp_t pub_sexpr;
440 gcry_mpi_t result_x;
441 unsigned char xbuf[256 / 8];
442 size_t rsize;
443
444 /* first, extract the q = dP value from the public key */
445 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
446 "(public-key(ecc(curve " CURVE ")(q %b)))",
447 (int)sizeof (pub->q_y), pub->q_y))
448 return 0;
449 rc = gcry_mpi_ec_new (&ctx, pub_sexpr, NULL);
450 brandt_assert_gpgerr (rc);
451 gcry_sexp_release (pub_sexpr);
452 q = gcry_mpi_ec_get_point ("q", ctx, 0);
453
454 /* second, extract the d value from our private key */
455 brandt_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
456
457 /* then call the 'multiply' function, to compute the product */
458 result = gcry_mpi_point_new (0);
459 gcry_mpi_ec_mul (result, d, q, ctx);
460 gcry_mpi_point_release (q);
461 gcry_mpi_release (d);
462
463 /* finally, convert point to string for hashing */
464 result_x = gcry_mpi_new (256);
465 rc = gcry_mpi_ec_get_affine (result_x, NULL, result, ctx);
466 brandt_assert (0 == rc);
467 gcry_mpi_point_release (result);
468 gcry_ctx_release (ctx);
469
470 rsize = sizeof (xbuf);
471 rc2 = gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE);
472 brandt_assert (0 == rc2);
473 /* result_x can be negative here, so we do not use 'brandt_mpi_print_unsigned'
474 * as that does not include the sign bit; x should be a 255-bit
475 * value, so with the sign it should fit snugly into the 256-bit
476 * xbuf */
477 rc = gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x);
478 brandt_assert_gpgerr (rc);
479 brandt_hash (xbuf, rsize, key_material);
480 gcry_mpi_release (result_x);
481 return 1;
482}
483 317
484/** 318/**
485 * Clear memory that was used to store a private key. 319 * Clear memory that was used to store a private key.
@@ -492,6 +326,7 @@ brandt_ec_key_clear (struct brandt_ec_skey *skey)
492 memset (skey, 0, sizeof (struct brandt_ec_skey)); 326 memset (skey, 0, sizeof (struct brandt_ec_skey));
493} 327}
494 328
329
495/** 330/**
496 * Generate a random value mod n. 331 * Generate a random value mod n.
497 * 332 *