Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2020, 2021, 2022 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file util/test_helper_rsa.c
18 : * @brief Tests for RSA crypto helper
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "taler/taler_util.h"
23 :
24 : /**
25 : * Configuration has 1 minute duration and 5 minutes lookahead, but
26 : * we do not get 'revocations' for expired keys. So this must be
27 : * large enough to deal with key rotation during the runtime of
28 : * the benchmark.
29 : */
30 : #define MAX_KEYS 1024
31 :
32 : /**
33 : * How many random key revocations should we test?
34 : */
35 : #define NUM_REVOKES 3
36 :
37 : /**
38 : * How many iterations of the successful signing test should we run?
39 : */
40 : #define NUM_SIGN_TESTS 5
41 :
42 : /**
43 : * How many iterations of the successful signing test should we run
44 : * during the benchmark phase?
45 : */
46 : #define NUM_SIGN_PERFS 100
47 :
48 : /**
49 : * How many parallel clients should we use for the parallel
50 : * benchmark? (> 500 may cause problems with the max open FD number limit).
51 : */
52 : #define NUM_CORES 8
53 :
54 : /**
55 : * Number of keys currently in #keys.
56 : */
57 : static unsigned int num_keys;
58 :
59 : /**
60 : * Keys currently managed by the helper.
61 : */
62 : struct KeyData
63 : {
64 : /**
65 : * Validity start point.
66 : */
67 : struct GNUNET_TIME_Timestamp start_time;
68 :
69 : /**
70 : * Key expires for signing at @e start_time plus this value.
71 : */
72 : struct GNUNET_TIME_Relative validity_duration;
73 :
74 : /**
75 : * Hash of the public key.
76 : */
77 : struct TALER_RsaPubHashP h_rsa;
78 :
79 : /**
80 : * Full public key.
81 : */
82 : struct TALER_DenominationPublicKey denom_pub;
83 :
84 : /**
85 : * Is this key currently valid?
86 : */
87 : bool valid;
88 :
89 : /**
90 : * Did the test driver revoke this key?
91 : */
92 : bool revoked;
93 : };
94 :
95 : /**
96 : * Array of all the keys we got from the helper.
97 : */
98 : static struct KeyData keys[MAX_KEYS];
99 :
100 :
101 : /**
102 : * Release memory occupied by #keys.
103 : */
104 : static void
105 9 : free_keys (void)
106 : {
107 9225 : for (unsigned int i = 0; i<MAX_KEYS; i++)
108 9216 : if (keys[i].valid)
109 : {
110 69 : TALER_denom_pub_free (&keys[i].denom_pub);
111 69 : keys[i].valid = false;
112 69 : GNUNET_assert (num_keys > 0);
113 69 : num_keys--;
114 : }
115 9 : }
116 :
117 :
118 : /**
119 : * Function called with information about available keys for signing. Usually
120 : * only called once per key upon connect. Also called again in case a key is
121 : * being revoked, in that case with an @a end_time of zero. Stores the keys
122 : * status in #keys.
123 : *
124 : * @param cls closure, NULL
125 : * @param section_name name of the denomination type in the configuration;
126 : * NULL if the key has been revoked or purged
127 : * @param start_time when does the key become available for signing;
128 : * zero if the key has been revoked or purged
129 : * @param validity_duration how long does the key remain available for signing;
130 : * zero if the key has been revoked or purged
131 : * @param h_rsa hash of the @a denom_pub that is available (or was purged)
132 : * @param bs_pub the public key itself, NULL if the key was revoked or purged
133 : * @param sm_pub public key of the security module, NULL if the key was revoked or purged
134 : * @param sm_sig signature from the security module, NULL if the key was revoked or purged
135 : * The signature was already verified against @a sm_pub.
136 : */
137 : static void
138 75 : key_cb (void *cls,
139 : const char *section_name,
140 : struct GNUNET_TIME_Timestamp start_time,
141 : struct GNUNET_TIME_Relative validity_duration,
142 : const struct TALER_RsaPubHashP *h_rsa,
143 : struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
144 : const struct TALER_SecurityModulePublicKeyP *sm_pub,
145 : const struct TALER_SecurityModuleSignatureP *sm_sig)
146 : {
147 : (void) cls;
148 : (void) sm_pub;
149 : (void) sm_sig;
150 75 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
151 : "Key notification about key %s in `%s'\n",
152 : GNUNET_h2s (&h_rsa->hash),
153 : section_name);
154 75 : if (0 == validity_duration.rel_value_us)
155 : {
156 3 : bool found = false;
157 :
158 3 : GNUNET_break (NULL == bs_pub);
159 3 : GNUNET_break (NULL == section_name);
160 13 : for (unsigned int i = 0; i<MAX_KEYS; i++)
161 13 : if (0 == GNUNET_memcmp (h_rsa,
162 : &keys[i].h_rsa))
163 : {
164 3 : keys[i].valid = false;
165 3 : keys[i].revoked = false;
166 3 : TALER_denom_pub_free (&keys[i].denom_pub);
167 3 : GNUNET_assert (num_keys > 0);
168 3 : num_keys--;
169 3 : found = true;
170 3 : break;
171 : }
172 3 : if (! found)
173 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
174 : "Error: helper announced expiration of unknown key!\n");
175 :
176 3 : return;
177 : }
178 :
179 72 : GNUNET_break (NULL != bs_pub);
180 316 : for (unsigned int i = 0; i<MAX_KEYS; i++)
181 316 : if (! keys[i].valid)
182 : {
183 72 : keys[i].valid = true;
184 72 : keys[i].h_rsa = *h_rsa;
185 72 : keys[i].start_time = start_time;
186 72 : keys[i].validity_duration = validity_duration;
187 : keys[i].denom_pub.bsign_pub_key
188 72 : = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
189 72 : num_keys++;
190 72 : return;
191 : }
192 : /* too many keys! */
193 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
194 : "Error: received %d live keys from the service!\n",
195 : MAX_KEYS + 1);
196 : }
197 :
198 :
199 : /**
200 : * Test key revocation logic.
201 : *
202 : * @param dh handle to the helper
203 : * @return 0 on success
204 : */
205 : static int
206 1 : test_revocation (struct TALER_CRYPTO_RsaDenominationHelper *dh)
207 : {
208 1 : struct timespec req = {
209 : .tv_nsec = 250000000
210 : };
211 :
212 4 : for (unsigned int i = 0; i<NUM_REVOKES; i++)
213 : {
214 : uint32_t off;
215 :
216 3 : off = GNUNET_CRYPTO_random_u32 (num_keys);
217 : /* find index of key to revoke */
218 13 : for (unsigned int j = 0; j < MAX_KEYS; j++)
219 : {
220 13 : if (! keys[j].valid)
221 0 : continue;
222 13 : if (0 != off)
223 : {
224 10 : off--;
225 10 : continue;
226 : }
227 3 : keys[j].revoked = true;
228 3 : fprintf (stderr,
229 : "Revoking key %s ...",
230 3 : GNUNET_h2s (&keys[j].h_rsa.hash));
231 3 : TALER_CRYPTO_helper_rsa_revoke (dh,
232 3 : &keys[j].h_rsa);
233 6 : for (unsigned int k = 0; k<1000; k++)
234 : {
235 6 : TALER_CRYPTO_helper_rsa_poll (dh);
236 6 : if (! keys[j].revoked)
237 3 : break;
238 3 : nanosleep (&req, NULL);
239 3 : fprintf (stderr, ".");
240 : }
241 3 : if (keys[j].revoked)
242 : {
243 0 : fprintf (stderr,
244 : "\nFAILED: timeout trying to revoke key %u\n",
245 : j);
246 0 : TALER_CRYPTO_helper_rsa_disconnect (dh);
247 0 : return 2;
248 : }
249 3 : fprintf (stderr, "\n");
250 3 : break;
251 : }
252 : }
253 1 : return 0;
254 : }
255 :
256 :
257 : /**
258 : * Test signing logic.
259 : *
260 : * @param dh handle to the helper
261 : * @return 0 on success
262 : */
263 : static int
264 1 : test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh)
265 : {
266 : struct TALER_BlindedDenominationSignature ds;
267 : enum TALER_ErrorCode ec;
268 1 : bool success = false;
269 : struct TALER_PlanchetMasterSecretP ps;
270 : const struct TALER_ExchangeBlindingValues *alg_values
271 1 : = TALER_denom_ewv_rsa_singleton ();
272 : struct TALER_AgeCommitmentHashP ach;
273 : struct TALER_CoinPubHashP c_hash;
274 : struct TALER_CoinSpendPrivateKeyP coin_priv;
275 : union GNUNET_CRYPTO_BlindingSecretP bks;
276 :
277 1 : GNUNET_CRYPTO_random_block (&ps,
278 : sizeof (ps));
279 1 : TALER_planchet_setup_coin_priv (&ps,
280 : alg_values,
281 : &coin_priv);
282 1 : TALER_planchet_blinding_secret_create (&ps,
283 : alg_values,
284 : &bks);
285 1 : GNUNET_CRYPTO_random_block (&ach,
286 : sizeof(ach));
287 :
288 1025 : for (unsigned int i = 0; i<MAX_KEYS; i++)
289 : {
290 1024 : if (! keys[i].valid)
291 1019 : continue;
292 5 : if (GNUNET_CRYPTO_BSA_RSA !=
293 5 : keys[i].denom_pub.bsign_pub_key->cipher)
294 0 : continue;
295 : {
296 : struct TALER_PlanchetDetail pd;
297 :
298 5 : GNUNET_assert (GNUNET_YES ==
299 : TALER_planchet_prepare (&keys[i].denom_pub,
300 : alg_values,
301 : &bks,
302 : NULL,
303 : &coin_priv,
304 : &ach,
305 : &c_hash,
306 : &pd));
307 : {
308 5 : struct TALER_CRYPTO_RsaSignRequest rsr = {
309 5 : .h_rsa = &keys[i].h_rsa,
310 : .msg =
311 5 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
312 : blinded_msg,
313 : .msg_size =
314 5 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
315 : blinded_msg_size
316 : };
317 :
318 5 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
319 : "Requesting signature over %u bytes with key %s\n",
320 : (unsigned int) rsr.msg_size,
321 : GNUNET_h2s (&rsr.h_rsa->hash));
322 5 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
323 : 1,
324 : &rsr,
325 : &ds);
326 : }
327 5 : TALER_blinded_planchet_free (&pd.blinded_planchet);
328 : }
329 5 : switch (ec)
330 : {
331 1 : case TALER_EC_NONE:
332 1 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
333 : keys[i].start_time.abs_time),
334 : >,
335 : GNUNET_TIME_UNIT_SECONDS))
336 : {
337 : /* key worked too early */
338 0 : GNUNET_break (0);
339 0 : return 4;
340 : }
341 1 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
342 : keys[i].start_time.abs_time),
343 : >,
344 : keys[i].validity_duration))
345 : {
346 : /* key worked too later */
347 0 : GNUNET_break (0);
348 0 : return 5;
349 : }
350 : {
351 : struct TALER_DenominationSignature rs;
352 :
353 1 : if (GNUNET_OK !=
354 1 : TALER_denom_sig_unblind (&rs,
355 : &ds,
356 : &bks,
357 : &c_hash,
358 : alg_values,
359 1 : &keys[i].denom_pub))
360 : {
361 0 : GNUNET_break (0);
362 0 : return 6;
363 : }
364 1 : TALER_blinded_denom_sig_free (&ds);
365 1 : if (GNUNET_OK !=
366 1 : TALER_denom_pub_verify (&keys[i].denom_pub,
367 : &rs,
368 : &c_hash))
369 : {
370 : /* signature invalid */
371 0 : GNUNET_break (0);
372 0 : TALER_denom_sig_free (&rs);
373 0 : return 7;
374 : }
375 1 : TALER_denom_sig_free (&rs);
376 : }
377 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
378 : "Received valid signature for key %s\n",
379 : GNUNET_h2s (&keys[i].h_rsa.hash));
380 1 : success = true;
381 1 : break;
382 4 : case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
383 : /* This 'failure' is expected, we're testing also for the
384 : error handling! */
385 4 : if ( (GNUNET_TIME_relative_is_zero (
386 : GNUNET_TIME_absolute_get_remaining (
387 0 : keys[i].start_time.abs_time))) &&
388 0 : (GNUNET_TIME_relative_cmp (
389 : GNUNET_TIME_absolute_get_duration (
390 : keys[i].start_time.abs_time),
391 : <,
392 : keys[i].validity_duration)) )
393 : {
394 : /* key should have worked! */
395 0 : GNUNET_break (0);
396 0 : return 6;
397 : }
398 4 : break;
399 0 : default:
400 : /* unexpected error */
401 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
402 : "Unexpected error %d at %s:%u\n",
403 : ec,
404 : __FILE__,
405 : __LINE__);
406 0 : return 7;
407 : }
408 : }
409 1 : if (! success)
410 : {
411 : /* no valid key for signing found, also bad */
412 0 : GNUNET_break (0);
413 0 : return 16;
414 : }
415 :
416 : /* check signing does not work if the key is unknown */
417 : {
418 : struct TALER_RsaPubHashP rnd;
419 1 : struct TALER_CRYPTO_RsaSignRequest rsr = {
420 : .h_rsa = &rnd,
421 : .msg = "Hello",
422 : .msg_size = strlen ("Hello")
423 : };
424 :
425 1 : GNUNET_CRYPTO_random_block (&rnd,
426 : sizeof (rnd));
427 1 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
428 : 1,
429 : &rsr,
430 : &ds);
431 1 : if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
432 : {
433 0 : if (TALER_EC_NONE == ec)
434 0 : TALER_blinded_denom_sig_free (&ds);
435 0 : GNUNET_break (0);
436 0 : return 17;
437 : }
438 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
439 : "Signing with invalid key %s failed as desired\n",
440 : GNUNET_h2s (&rnd.hash));
441 : }
442 1 : return 0;
443 : }
444 :
445 :
446 : /**
447 : * Test batch signing logic.
448 : *
449 : * @param dh handle to the helper
450 : * @param batch_size how large should the batch be
451 : * @param check_sigs also check unknown key and signatures
452 : * @return 0 on success
453 : */
454 : static int
455 6 : test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
456 : unsigned int batch_size,
457 : bool check_sigs)
458 6 : {
459 6 : struct TALER_BlindedDenominationSignature ds[batch_size];
460 : enum TALER_ErrorCode ec;
461 6 : bool success = false;
462 6 : struct TALER_PlanchetMasterSecretP ps[batch_size];
463 : const struct TALER_ExchangeBlindingValues *alg_values;
464 6 : struct TALER_AgeCommitmentHashP ach[batch_size];
465 6 : struct TALER_CoinPubHashP c_hash[batch_size];
466 6 : struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
467 6 : union GNUNET_CRYPTO_BlindingSecretP bks[batch_size];
468 :
469 6 : GNUNET_CRYPTO_random_block (&ps,
470 : sizeof (ps));
471 6 : GNUNET_CRYPTO_random_block (&ach,
472 : sizeof(ach));
473 6 : alg_values = TALER_denom_ewv_rsa_singleton ();
474 157 : for (unsigned int i = 0; i<batch_size; i++)
475 : {
476 151 : TALER_planchet_setup_coin_priv (&ps[i],
477 : alg_values,
478 : &coin_priv[i]);
479 151 : TALER_planchet_blinding_secret_create (&ps[i],
480 : alg_values,
481 : &bks[i]);
482 : }
483 2058 : for (unsigned int k = 0; k<MAX_KEYS; k++)
484 : {
485 2056 : if (success && ! check_sigs)
486 4 : break; /* only do one round */
487 2052 : if (! keys[k].valid)
488 2038 : continue;
489 14 : if (GNUNET_CRYPTO_BSA_RSA !=
490 14 : keys[k].denom_pub.bsign_pub_key->cipher)
491 0 : continue;
492 14 : {
493 14 : struct TALER_PlanchetDetail pd[batch_size];
494 14 : struct TALER_CRYPTO_RsaSignRequest rsr[batch_size];
495 :
496 429 : for (unsigned int i = 0; i<batch_size; i++)
497 : {
498 415 : GNUNET_assert (GNUNET_YES ==
499 : TALER_planchet_prepare (&keys[k].denom_pub,
500 : alg_values,
501 : &bks[i],
502 : NULL,
503 : &coin_priv[i],
504 : &ach[i],
505 : &c_hash[i],
506 : &pd[i]));
507 : rsr[i].h_rsa
508 415 : = &keys[k].h_rsa;
509 : rsr[i].msg
510 415 : = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message.
511 : blinded_msg;
512 : rsr[i].msg_size
513 415 : = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message.
514 : blinded_msg_size;
515 : }
516 14 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
517 : batch_size,
518 : rsr,
519 : ds);
520 429 : for (unsigned int i = 0; i<batch_size; i++)
521 : {
522 415 : if (TALER_EC_NONE == ec)
523 151 : GNUNET_break (GNUNET_CRYPTO_BSA_RSA ==
524 : ds[i].blinded_sig->cipher);
525 415 : TALER_blinded_planchet_free (&pd[i].blinded_planchet);
526 : }
527 : }
528 14 : switch (ec)
529 : {
530 6 : case TALER_EC_NONE:
531 6 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
532 : keys[k].start_time.abs_time),
533 : >,
534 : GNUNET_TIME_UNIT_SECONDS))
535 : {
536 : /* key worked too early */
537 0 : GNUNET_break (0);
538 0 : return 4;
539 : }
540 6 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
541 : keys[k].start_time.abs_time),
542 : >,
543 : keys[k].validity_duration))
544 : {
545 : /* key worked too later */
546 0 : GNUNET_break (0);
547 0 : return 5;
548 : }
549 157 : for (unsigned int i = 0; i<batch_size; i++)
550 : {
551 : struct TALER_DenominationSignature rs;
552 :
553 151 : if (check_sigs)
554 : {
555 66 : if (GNUNET_OK !=
556 66 : TALER_denom_sig_unblind (&rs,
557 66 : &ds[i],
558 66 : &bks[i],
559 66 : &c_hash[i],
560 : alg_values,
561 66 : &keys[k].denom_pub))
562 : {
563 0 : GNUNET_break (0);
564 0 : return 6;
565 : }
566 : }
567 151 : TALER_blinded_denom_sig_free (&ds[i]);
568 151 : if (check_sigs)
569 : {
570 66 : if (GNUNET_OK !=
571 66 : TALER_denom_pub_verify (&keys[k].denom_pub,
572 : &rs,
573 66 : &c_hash[i]))
574 : {
575 : /* signature invalid */
576 0 : GNUNET_break (0);
577 0 : TALER_denom_sig_free (&rs);
578 0 : return 7;
579 : }
580 66 : TALER_denom_sig_free (&rs);
581 : }
582 : }
583 6 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
584 : "Received valid signature for key %s\n",
585 : GNUNET_h2s (&keys[k].h_rsa.hash));
586 6 : success = true;
587 6 : break;
588 8 : case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
589 : /* This 'failure' is expected, we're testing also for the
590 : error handling! */
591 272 : for (unsigned int i = 0; i<batch_size; i++)
592 264 : TALER_blinded_denom_sig_free (&ds[i]);
593 8 : if ( (GNUNET_TIME_relative_is_zero (
594 : GNUNET_TIME_absolute_get_remaining (
595 0 : keys[k].start_time.abs_time))) &&
596 0 : (GNUNET_TIME_relative_cmp (
597 : GNUNET_TIME_absolute_get_duration (
598 : keys[k].start_time.abs_time),
599 : <,
600 : keys[k].validity_duration)) )
601 : {
602 : /* key should have worked! */
603 0 : GNUNET_break (0);
604 0 : return 6;
605 : }
606 8 : break;
607 0 : case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN:
608 0 : for (unsigned int i = 0; i<batch_size; i++)
609 0 : TALER_blinded_denom_sig_free (&ds[i]);
610 0 : break;
611 0 : default:
612 : /* unexpected error */
613 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
614 : "Unexpected error %d at %s:%u\n",
615 : ec,
616 : __FILE__,
617 : __LINE__);
618 0 : for (unsigned int i = 0; i<batch_size; i++)
619 0 : TALER_blinded_denom_sig_free (&ds[i]);
620 0 : return 7;
621 : }
622 : }
623 6 : if (! success)
624 : {
625 : /* no valid key for signing found, also bad */
626 0 : GNUNET_break (0);
627 0 : return 16;
628 : }
629 :
630 : /* check signing does not work if the key is unknown */
631 6 : if (check_sigs)
632 : {
633 : struct TALER_RsaPubHashP rnd;
634 2 : struct TALER_CRYPTO_RsaSignRequest rsr = {
635 : .h_rsa = &rnd,
636 : .msg = "Hello",
637 : .msg_size = strlen ("Hello")
638 : };
639 :
640 2 : GNUNET_CRYPTO_random_block (&rnd,
641 : sizeof (rnd));
642 2 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
643 : 1,
644 : &rsr,
645 : ds);
646 2 : if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
647 : {
648 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
649 : "Signing with invalid key returned unexpected status %d\n",
650 : ec);
651 0 : if (TALER_EC_NONE == ec)
652 0 : TALER_blinded_denom_sig_free (ds);
653 0 : GNUNET_break (0);
654 0 : return 17;
655 : }
656 2 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
657 : "Signing with invalid key %s failed as desired\n",
658 : GNUNET_h2s (&rnd.hash));
659 : }
660 6 : return 0;
661 : }
662 :
663 :
664 : /**
665 : * Benchmark signing logic.
666 : *
667 : * @param dh handle to the helper
668 : * @return 0 on success
669 : */
670 : static int
671 9 : perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
672 : const char *type)
673 : {
674 : struct TALER_BlindedDenominationSignature ds;
675 : enum TALER_ErrorCode ec;
676 : struct GNUNET_TIME_Relative duration;
677 : struct TALER_PlanchetMasterSecretP ps;
678 : struct TALER_CoinSpendPrivateKeyP coin_priv;
679 : struct TALER_AgeCommitmentHashP ach;
680 : union GNUNET_CRYPTO_BlindingSecretP bks;
681 : const struct TALER_ExchangeBlindingValues *alg_values
682 9 : = TALER_denom_ewv_rsa_singleton ();
683 :
684 9 : TALER_planchet_master_setup_random (&ps);
685 9 : TALER_planchet_setup_coin_priv (&ps,
686 : alg_values,
687 : &coin_priv);
688 9 : TALER_planchet_blinding_secret_create (&ps,
689 : alg_values,
690 : &bks);
691 9 : GNUNET_CRYPTO_random_block (&ach,
692 : sizeof(ach));
693 9 : duration = GNUNET_TIME_UNIT_ZERO;
694 9 : TALER_CRYPTO_helper_rsa_poll (dh);
695 18 : for (unsigned int j = 0; j<NUM_SIGN_PERFS;)
696 : {
697 9225 : for (unsigned int i = 0; i<MAX_KEYS; i++)
698 : {
699 9216 : if (! keys[i].valid)
700 9147 : continue;
701 69 : if (GNUNET_CRYPTO_BSA_RSA !=
702 69 : keys[i].denom_pub.bsign_pub_key->cipher)
703 0 : continue;
704 69 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
705 : keys[i].start_time.abs_time),
706 : >,
707 : GNUNET_TIME_UNIT_SECONDS))
708 60 : continue;
709 9 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
710 : keys[i].start_time.abs_time),
711 : >,
712 : keys[i].validity_duration))
713 0 : continue;
714 : {
715 : struct TALER_CoinPubHashP c_hash;
716 : struct TALER_PlanchetDetail pd;
717 :
718 9 : GNUNET_assert (GNUNET_YES ==
719 : TALER_planchet_prepare (&keys[i].denom_pub,
720 : alg_values,
721 : &bks,
722 : NULL,
723 : &coin_priv,
724 : &ach,
725 : &c_hash,
726 : &pd));
727 : /* use this key as long as it works */
728 : while (1)
729 891 : {
730 900 : struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get ();
731 : struct GNUNET_TIME_Relative delay;
732 900 : struct TALER_CRYPTO_RsaSignRequest rsr = {
733 900 : .h_rsa = &keys[i].h_rsa,
734 : .msg =
735 900 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
736 : blinded_msg,
737 : .msg_size =
738 900 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
739 : blinded_msg_size
740 : };
741 :
742 900 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
743 : 1,
744 : &rsr,
745 : &ds);
746 900 : if (TALER_EC_NONE != ec)
747 0 : break;
748 900 : delay = GNUNET_TIME_absolute_get_duration (start);
749 900 : duration = GNUNET_TIME_relative_add (duration,
750 : delay);
751 900 : TALER_blinded_denom_sig_free (&ds);
752 900 : j++;
753 900 : if (NUM_SIGN_PERFS <= j)
754 9 : break;
755 : }
756 9 : TALER_blinded_planchet_free (&pd.blinded_planchet);
757 : }
758 : } /* for i */
759 : } /* for j */
760 9 : fprintf (stderr,
761 : "%u (%s) signature operations took %s\n",
762 : (unsigned int) NUM_SIGN_PERFS,
763 : type,
764 : GNUNET_STRINGS_relative_time_to_string (duration,
765 : GNUNET_YES));
766 9 : return 0;
767 : }
768 :
769 :
770 : /**
771 : * Parallel signing logic.
772 : *
773 : * @param esh handle to the helper
774 : * @return 0 on success
775 : */
776 : static int
777 1 : par_signing (struct GNUNET_CONFIGURATION_Handle *cfg)
778 : {
779 : struct GNUNET_TIME_Absolute start;
780 : struct GNUNET_TIME_Relative duration;
781 : pid_t pids[NUM_CORES];
782 : struct TALER_CRYPTO_RsaDenominationHelper *dh;
783 :
784 1 : start = GNUNET_TIME_absolute_get ();
785 9 : for (unsigned int i = 0; i<NUM_CORES; i++)
786 : {
787 8 : pids[i] = fork ();
788 16 : num_keys = 0;
789 16 : GNUNET_assert (-1 != pids[i]);
790 16 : if (0 == pids[i])
791 : {
792 : int ret;
793 :
794 8 : dh = TALER_CRYPTO_helper_rsa_connect (cfg,
795 : "taler-exchange",
796 : &key_cb,
797 : NULL);
798 8 : GNUNET_assert (NULL != dh);
799 8 : ret = perf_signing (dh,
800 : "parallel");
801 8 : TALER_CRYPTO_helper_rsa_disconnect (dh);
802 8 : free_keys ();
803 8 : exit (ret);
804 : }
805 : }
806 9 : for (unsigned int i = 0; i<NUM_CORES; i++)
807 : {
808 : int wstatus;
809 :
810 8 : GNUNET_assert (pids[i] ==
811 : waitpid (pids[i],
812 : &wstatus,
813 : 0));
814 : }
815 1 : duration = GNUNET_TIME_absolute_get_duration (start);
816 1 : fprintf (stderr,
817 : "%u (parallel) signature operations took %s (total real time)\n",
818 : (unsigned int) NUM_SIGN_PERFS * NUM_CORES,
819 : GNUNET_STRINGS_relative_time_to_string (duration,
820 : GNUNET_YES));
821 1 : return 0;
822 : }
823 :
824 :
825 : /**
826 : * Main entry point into the test logic with the helper already running.
827 : */
828 : static int
829 1 : run_test (void)
830 : {
831 : struct GNUNET_CONFIGURATION_Handle *cfg;
832 : struct TALER_CRYPTO_RsaDenominationHelper *dh;
833 1 : struct timespec req = {
834 : .tv_nsec = 250000000
835 : };
836 : int ret;
837 :
838 1 : cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
839 1 : if (GNUNET_OK !=
840 1 : GNUNET_CONFIGURATION_load (cfg,
841 : "test_helper_rsa.conf"))
842 : {
843 0 : GNUNET_break (0);
844 0 : return 77;
845 : }
846 :
847 1 : fprintf (stderr,
848 : "Waiting for helper to start ... ");
849 1 : for (unsigned int i = 0; i<100; i++)
850 : {
851 1 : nanosleep (&req,
852 : NULL);
853 1 : dh = TALER_CRYPTO_helper_rsa_connect (cfg,
854 : "taler-exchange",
855 : &key_cb,
856 : NULL);
857 1 : if (NULL != dh)
858 1 : break;
859 0 : fprintf (stderr, ".");
860 : }
861 1 : if (NULL == dh)
862 : {
863 0 : fprintf (stderr,
864 : "\nFAILED: timeout trying to connect to helper\n");
865 0 : GNUNET_CONFIGURATION_destroy (cfg);
866 0 : return 1;
867 : }
868 1 : if (0 == num_keys)
869 : {
870 0 : fprintf (stderr,
871 : "\nFAILED: timeout trying to connect to helper\n");
872 0 : TALER_CRYPTO_helper_rsa_disconnect (dh);
873 0 : GNUNET_CONFIGURATION_destroy (cfg);
874 0 : return 1;
875 : }
876 1 : fprintf (stderr,
877 : " Done (%u keys)\n",
878 : num_keys);
879 1 : ret = 0;
880 1 : if (0 == ret)
881 1 : ret = test_revocation (dh);
882 1 : if (0 == ret)
883 1 : ret = test_signing (dh);
884 1 : if (0 == ret)
885 1 : ret = test_batch_signing (dh,
886 : 2,
887 : true);
888 1 : if (0 == ret)
889 1 : ret = test_batch_signing (dh,
890 : 64,
891 : true);
892 5 : for (unsigned int i = 0; i<4; i++)
893 : {
894 : static unsigned int batches[] = { 1, 4, 16, 64 };
895 4 : unsigned int batch_size = batches[i];
896 : struct GNUNET_TIME_Absolute start;
897 : struct GNUNET_TIME_Relative duration;
898 :
899 4 : start = GNUNET_TIME_absolute_get ();
900 4 : if (0 != ret)
901 0 : break;
902 4 : ret = test_batch_signing (dh,
903 : batch_size,
904 : false);
905 4 : duration = GNUNET_TIME_absolute_get_duration (start);
906 4 : fprintf (stderr,
907 : "%4u (batch) signature operations took %s (total real time)\n",
908 : (unsigned int) batch_size,
909 : GNUNET_STRINGS_relative_time_to_string (duration,
910 : GNUNET_YES));
911 : }
912 1 : if (0 == ret)
913 1 : ret = perf_signing (dh,
914 : "sequential");
915 1 : TALER_CRYPTO_helper_rsa_disconnect (dh);
916 1 : free_keys ();
917 1 : if (0 == ret)
918 1 : ret = par_signing (cfg);
919 : /* clean up our state */
920 1 : GNUNET_CONFIGURATION_destroy (cfg);
921 1 : return ret;
922 : }
923 :
924 :
925 : int
926 1 : main (int argc,
927 : const char *const argv[])
928 : {
929 1 : const char *loglevel = "WARNING";
930 : struct GNUNET_Process *helper;
931 : char *libexec_dir;
932 : char *binary_name;
933 : int ret;
934 : enum GNUNET_OS_ProcessStatusType type;
935 : unsigned long code;
936 :
937 : (void) argc;
938 : (void) argv;
939 1 : unsetenv ("XDG_DATA_HOME");
940 1 : unsetenv ("XDG_CONFIG_HOME");
941 1 : GNUNET_log_setup ("test-helper-rsa",
942 : loglevel,
943 : NULL);
944 1 : libexec_dir = GNUNET_OS_installation_get_path (TALER_EXCHANGE_project_data (),
945 : GNUNET_OS_IPK_BINDIR);
946 1 : GNUNET_asprintf (&binary_name,
947 : "%s/%s",
948 : libexec_dir,
949 : "taler-exchange-secmod-rsa");
950 1 : GNUNET_free (libexec_dir);
951 1 : helper = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR);
952 1 : if (GNUNET_OK !=
953 1 : GNUNET_process_run_command_va (helper,
954 : binary_name,
955 : binary_name,
956 : "-c",
957 : "test_helper_rsa.conf",
958 : "-L",
959 : loglevel,
960 : NULL))
961 : {
962 0 : GNUNET_process_destroy (helper);
963 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
964 : "exec",
965 : binary_name);
966 0 : GNUNET_free (binary_name);
967 0 : return 77;
968 : }
969 1 : GNUNET_free (binary_name);
970 1 : ret = run_test ();
971 :
972 1 : GNUNET_break (GNUNET_OK ==
973 : GNUNET_process_kill (helper,
974 : SIGTERM));
975 1 : if (GNUNET_OK !=
976 1 : GNUNET_process_wait (helper,
977 : true,
978 : &type,
979 : &code))
980 : {
981 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
982 : "Helper process did not die voluntarily, killing hard\n");
983 0 : GNUNET_break (GNUNET_OK ==
984 : GNUNET_process_kill (helper,
985 : SIGKILL));
986 0 : ret = 4;
987 : }
988 1 : else if ( (GNUNET_OS_PROCESS_EXITED != type) ||
989 1 : (0 != code) )
990 : {
991 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
992 : "Helper died with unexpected status %d/%d\n",
993 : (int) type,
994 : (int) code);
995 0 : ret = 5;
996 : }
997 1 : GNUNET_process_destroy (helper);
998 1 : return ret;
999 : }
1000 :
1001 :
1002 : /* end of test_helper_rsa.c */
|