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_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 78 : TALER_denom_pub_free (&keys[i].denom_pub);
111 78 : keys[i].valid = false;
112 78 : GNUNET_assert (num_keys > 0);
113 78 : 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 84 : 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 84 : 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 84 : 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 14 : for (unsigned int i = 0; i<MAX_KEYS; i++)
161 14 : 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 81 : GNUNET_break (NULL != bs_pub);
180 395 : for (unsigned int i = 0; i<MAX_KEYS; i++)
181 395 : if (! keys[i].valid)
182 : {
183 81 : keys[i].valid = true;
184 81 : keys[i].h_rsa = *h_rsa;
185 81 : keys[i].start_time = start_time;
186 81 : keys[i].validity_duration = validity_duration;
187 : keys[i].denom_pub.bsign_pub_key
188 81 : = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
189 81 : num_keys++;
190 81 : 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 (GNUNET_CRYPTO_QUALITY_WEAK,
217 : num_keys);
218 : /* find index of key to revoke */
219 14 : for (unsigned int j = 0; j < MAX_KEYS; j++)
220 : {
221 14 : if (! keys[j].valid)
222 0 : continue;
223 14 : if (0 != off)
224 : {
225 11 : off--;
226 11 : continue;
227 : }
228 3 : keys[j].revoked = true;
229 3 : fprintf (stderr,
230 : "Revoking key %s ...",
231 3 : GNUNET_h2s (&keys[j].h_rsa.hash));
232 3 : TALER_CRYPTO_helper_rsa_revoke (dh,
233 3 : &keys[j].h_rsa);
234 7 : for (unsigned int k = 0; k<1000; k++)
235 : {
236 7 : TALER_CRYPTO_helper_rsa_poll (dh);
237 7 : if (! keys[j].revoked)
238 3 : break;
239 4 : nanosleep (&req, NULL);
240 4 : fprintf (stderr, ".");
241 : }
242 3 : if (keys[j].revoked)
243 : {
244 0 : fprintf (stderr,
245 : "\nFAILED: timeout trying to revoke key %u\n",
246 : j);
247 0 : TALER_CRYPTO_helper_rsa_disconnect (dh);
248 0 : return 2;
249 : }
250 3 : fprintf (stderr, "\n");
251 3 : break;
252 : }
253 : }
254 1 : return 0;
255 : }
256 :
257 :
258 : /**
259 : * Test signing logic.
260 : *
261 : * @param dh handle to the helper
262 : * @return 0 on success
263 : */
264 : static int
265 1 : test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh)
266 : {
267 : struct TALER_BlindedDenominationSignature ds;
268 : enum TALER_ErrorCode ec;
269 1 : bool success = false;
270 : struct TALER_PlanchetMasterSecretP ps;
271 : const struct TALER_ExchangeBlindingValues *alg_values
272 1 : = TALER_denom_ewv_rsa_singleton ();
273 : struct TALER_AgeCommitmentHash ach;
274 : struct TALER_CoinPubHashP c_hash;
275 : struct TALER_CoinSpendPrivateKeyP coin_priv;
276 : union GNUNET_CRYPTO_BlindingSecretP bks;
277 :
278 1 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
279 : &ps,
280 : sizeof (ps));
281 1 : TALER_planchet_setup_coin_priv (&ps,
282 : alg_values,
283 : &coin_priv);
284 1 : TALER_planchet_blinding_secret_create (&ps,
285 : alg_values,
286 : &bks);
287 1 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
288 : &ach,
289 : sizeof(ach));
290 :
291 1025 : for (unsigned int i = 0; i<MAX_KEYS; i++)
292 : {
293 1024 : if (! keys[i].valid)
294 1018 : continue;
295 6 : if (GNUNET_CRYPTO_BSA_RSA !=
296 6 : keys[i].denom_pub.bsign_pub_key->cipher)
297 0 : continue;
298 : {
299 : struct TALER_PlanchetDetail pd;
300 :
301 6 : GNUNET_assert (GNUNET_YES ==
302 : TALER_planchet_prepare (&keys[i].denom_pub,
303 : alg_values,
304 : &bks,
305 : NULL,
306 : &coin_priv,
307 : &ach,
308 : &c_hash,
309 : &pd));
310 : {
311 6 : struct TALER_CRYPTO_RsaSignRequest rsr = {
312 6 : .h_rsa = &keys[i].h_rsa,
313 : .msg =
314 6 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
315 : blinded_msg,
316 : .msg_size =
317 6 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
318 : blinded_msg_size
319 : };
320 :
321 6 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
322 : "Requesting signature over %u bytes with key %s\n",
323 : (unsigned int) rsr.msg_size,
324 : GNUNET_h2s (&rsr.h_rsa->hash));
325 6 : ec = TALER_CRYPTO_helper_rsa_sign (dh,
326 : &rsr,
327 : &ds);
328 : }
329 6 : TALER_blinded_planchet_free (&pd.blinded_planchet);
330 : }
331 6 : switch (ec)
332 : {
333 1 : case TALER_EC_NONE:
334 1 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
335 : keys[i].start_time.abs_time),
336 : >,
337 : GNUNET_TIME_UNIT_SECONDS))
338 : {
339 : /* key worked too early */
340 0 : GNUNET_break (0);
341 0 : return 4;
342 : }
343 1 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
344 : keys[i].start_time.abs_time),
345 : >,
346 : keys[i].validity_duration))
347 : {
348 : /* key worked too later */
349 0 : GNUNET_break (0);
350 0 : return 5;
351 : }
352 : {
353 : struct TALER_DenominationSignature rs;
354 :
355 1 : if (GNUNET_OK !=
356 1 : TALER_denom_sig_unblind (&rs,
357 : &ds,
358 : &bks,
359 : &c_hash,
360 : alg_values,
361 1 : &keys[i].denom_pub))
362 : {
363 0 : GNUNET_break (0);
364 0 : return 6;
365 : }
366 1 : TALER_blinded_denom_sig_free (&ds);
367 1 : if (GNUNET_OK !=
368 1 : TALER_denom_pub_verify (&keys[i].denom_pub,
369 : &rs,
370 : &c_hash))
371 : {
372 : /* signature invalid */
373 0 : GNUNET_break (0);
374 0 : TALER_denom_sig_free (&rs);
375 0 : return 7;
376 : }
377 1 : TALER_denom_sig_free (&rs);
378 : }
379 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
380 : "Received valid signature for key %s\n",
381 : GNUNET_h2s (&keys[i].h_rsa.hash));
382 1 : success = true;
383 1 : break;
384 5 : case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
385 : /* This 'failure' is expected, we're testing also for the
386 : error handling! */
387 5 : if ( (GNUNET_TIME_relative_is_zero (
388 : GNUNET_TIME_absolute_get_remaining (
389 0 : keys[i].start_time.abs_time))) &&
390 0 : (GNUNET_TIME_relative_cmp (
391 : GNUNET_TIME_absolute_get_duration (
392 : keys[i].start_time.abs_time),
393 : <,
394 : keys[i].validity_duration)) )
395 : {
396 : /* key should have worked! */
397 0 : GNUNET_break (0);
398 0 : return 6;
399 : }
400 5 : break;
401 0 : default:
402 : /* unexpected error */
403 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
404 : "Unexpected error %d at %s:%u\n",
405 : ec,
406 : __FILE__,
407 : __LINE__);
408 0 : return 7;
409 : }
410 : }
411 1 : if (! success)
412 : {
413 : /* no valid key for signing found, also bad */
414 0 : GNUNET_break (0);
415 0 : return 16;
416 : }
417 :
418 : /* check signing does not work if the key is unknown */
419 : {
420 : struct TALER_RsaPubHashP rnd;
421 1 : struct TALER_CRYPTO_RsaSignRequest rsr = {
422 : .h_rsa = &rnd,
423 : .msg = "Hello",
424 : .msg_size = strlen ("Hello")
425 : };
426 :
427 1 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
428 : &rnd,
429 : sizeof (rnd));
430 1 : ec = TALER_CRYPTO_helper_rsa_sign (dh,
431 : &rsr,
432 : &ds);
433 1 : if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
434 : {
435 0 : if (TALER_EC_NONE == ec)
436 0 : TALER_blinded_denom_sig_free (&ds);
437 0 : GNUNET_break (0);
438 0 : return 17;
439 : }
440 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
441 : "Signing with invalid key %s failed as desired\n",
442 : GNUNET_h2s (&rnd.hash));
443 : }
444 1 : return 0;
445 : }
446 :
447 :
448 : /**
449 : * Test batch signing logic.
450 : *
451 : * @param dh handle to the helper
452 : * @param batch_size how large should the batch be
453 : * @param check_sigs also check unknown key and signatures
454 : * @return 0 on success
455 : */
456 : static int
457 6 : test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
458 : unsigned int batch_size,
459 : bool check_sigs)
460 6 : {
461 6 : struct TALER_BlindedDenominationSignature ds[batch_size];
462 : enum TALER_ErrorCode ec;
463 6 : bool success = false;
464 6 : struct TALER_PlanchetMasterSecretP ps[batch_size];
465 : const struct TALER_ExchangeBlindingValues *alg_values;
466 6 : struct TALER_AgeCommitmentHash ach[batch_size];
467 6 : struct TALER_CoinPubHashP c_hash[batch_size];
468 6 : struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
469 6 : union GNUNET_CRYPTO_BlindingSecretP bks[batch_size];
470 :
471 6 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
472 : &ps,
473 : sizeof (ps));
474 6 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
475 : &ach,
476 : sizeof(ach));
477 6 : alg_values = TALER_denom_ewv_rsa_singleton ();
478 157 : for (unsigned int i = 0; i<batch_size; i++)
479 : {
480 151 : TALER_planchet_setup_coin_priv (&ps[i],
481 : alg_values,
482 : &coin_priv[i]);
483 151 : TALER_planchet_blinding_secret_create (&ps[i],
484 : alg_values,
485 : &bks[i]);
486 : }
487 2058 : for (unsigned int k = 0; k<MAX_KEYS; k++)
488 : {
489 2056 : if (success && ! check_sigs)
490 4 : break; /* only do one round */
491 2052 : if (! keys[k].valid)
492 2036 : continue;
493 16 : if (GNUNET_CRYPTO_BSA_RSA !=
494 16 : keys[k].denom_pub.bsign_pub_key->cipher)
495 0 : continue;
496 16 : {
497 16 : struct TALER_PlanchetDetail pd[batch_size];
498 16 : struct TALER_CRYPTO_RsaSignRequest rsr[batch_size];
499 :
500 497 : for (unsigned int i = 0; i<batch_size; i++)
501 : {
502 481 : GNUNET_assert (GNUNET_YES ==
503 : TALER_planchet_prepare (&keys[k].denom_pub,
504 : alg_values,
505 : &bks[i],
506 : NULL,
507 : &coin_priv[i],
508 : &ach[i],
509 : &c_hash[i],
510 : &pd[i]));
511 : rsr[i].h_rsa
512 481 : = &keys[k].h_rsa;
513 : rsr[i].msg
514 481 : = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message.
515 : blinded_msg;
516 : rsr[i].msg_size
517 481 : = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message.
518 : blinded_msg_size;
519 : }
520 16 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
521 : batch_size,
522 : rsr,
523 : ds);
524 497 : for (unsigned int i = 0; i<batch_size; i++)
525 : {
526 481 : if (TALER_EC_NONE == ec)
527 151 : GNUNET_break (GNUNET_CRYPTO_BSA_RSA ==
528 : ds[i].blinded_sig->cipher);
529 481 : TALER_blinded_planchet_free (&pd[i].blinded_planchet);
530 : }
531 : }
532 16 : switch (ec)
533 : {
534 6 : case TALER_EC_NONE:
535 6 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
536 : keys[k].start_time.abs_time),
537 : >,
538 : GNUNET_TIME_UNIT_SECONDS))
539 : {
540 : /* key worked too early */
541 0 : GNUNET_break (0);
542 0 : return 4;
543 : }
544 6 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
545 : keys[k].start_time.abs_time),
546 : >,
547 : keys[k].validity_duration))
548 : {
549 : /* key worked too later */
550 0 : GNUNET_break (0);
551 0 : return 5;
552 : }
553 157 : for (unsigned int i = 0; i<batch_size; i++)
554 : {
555 : struct TALER_DenominationSignature rs;
556 :
557 151 : if (check_sigs)
558 : {
559 66 : if (GNUNET_OK !=
560 66 : TALER_denom_sig_unblind (&rs,
561 66 : &ds[i],
562 66 : &bks[i],
563 66 : &c_hash[i],
564 : alg_values,
565 66 : &keys[k].denom_pub))
566 : {
567 0 : GNUNET_break (0);
568 0 : return 6;
569 : }
570 : }
571 151 : TALER_blinded_denom_sig_free (&ds[i]);
572 151 : if (check_sigs)
573 : {
574 66 : if (GNUNET_OK !=
575 66 : TALER_denom_pub_verify (&keys[k].denom_pub,
576 : &rs,
577 66 : &c_hash[i]))
578 : {
579 : /* signature invalid */
580 0 : GNUNET_break (0);
581 0 : TALER_denom_sig_free (&rs);
582 0 : return 7;
583 : }
584 66 : TALER_denom_sig_free (&rs);
585 : }
586 : }
587 6 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
588 : "Received valid signature for key %s\n",
589 : GNUNET_h2s (&keys[k].h_rsa.hash));
590 6 : success = true;
591 6 : break;
592 10 : case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
593 : /* This 'failure' is expected, we're testing also for the
594 : error handling! */
595 340 : for (unsigned int i = 0; i<batch_size; i++)
596 330 : TALER_blinded_denom_sig_free (&ds[i]);
597 10 : if ( (GNUNET_TIME_relative_is_zero (
598 : GNUNET_TIME_absolute_get_remaining (
599 0 : keys[k].start_time.abs_time))) &&
600 0 : (GNUNET_TIME_relative_cmp (
601 : GNUNET_TIME_absolute_get_duration (
602 : keys[k].start_time.abs_time),
603 : <,
604 : keys[k].validity_duration)) )
605 : {
606 : /* key should have worked! */
607 0 : GNUNET_break (0);
608 0 : return 6;
609 : }
610 10 : break;
611 0 : case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN:
612 0 : for (unsigned int i = 0; i<batch_size; i++)
613 0 : TALER_blinded_denom_sig_free (&ds[i]);
614 0 : break;
615 0 : default:
616 : /* unexpected error */
617 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
618 : "Unexpected error %d at %s:%u\n",
619 : ec,
620 : __FILE__,
621 : __LINE__);
622 0 : for (unsigned int i = 0; i<batch_size; i++)
623 0 : TALER_blinded_denom_sig_free (&ds[i]);
624 0 : return 7;
625 : }
626 : }
627 6 : if (! success)
628 : {
629 : /* no valid key for signing found, also bad */
630 0 : GNUNET_break (0);
631 0 : return 16;
632 : }
633 :
634 : /* check signing does not work if the key is unknown */
635 6 : if (check_sigs)
636 : {
637 : struct TALER_RsaPubHashP rnd;
638 2 : struct TALER_CRYPTO_RsaSignRequest rsr = {
639 : .h_rsa = &rnd,
640 : .msg = "Hello",
641 : .msg_size = strlen ("Hello")
642 : };
643 :
644 2 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
645 : &rnd,
646 : sizeof (rnd));
647 2 : ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
648 : 1,
649 : &rsr,
650 : ds);
651 2 : if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
652 : {
653 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
654 : "Signing with invalid key returned unexpected status %d\n",
655 : ec);
656 0 : if (TALER_EC_NONE == ec)
657 0 : TALER_blinded_denom_sig_free (ds);
658 0 : GNUNET_break (0);
659 0 : return 17;
660 : }
661 2 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
662 : "Signing with invalid key %s failed as desired\n",
663 : GNUNET_h2s (&rnd.hash));
664 : }
665 6 : return 0;
666 : }
667 :
668 :
669 : /**
670 : * Benchmark signing logic.
671 : *
672 : * @param dh handle to the helper
673 : * @return 0 on success
674 : */
675 : static int
676 9 : perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
677 : const char *type)
678 : {
679 : struct TALER_BlindedDenominationSignature ds;
680 : enum TALER_ErrorCode ec;
681 : struct GNUNET_TIME_Relative duration;
682 : struct TALER_PlanchetMasterSecretP ps;
683 : struct TALER_CoinSpendPrivateKeyP coin_priv;
684 : struct TALER_AgeCommitmentHash ach;
685 : union GNUNET_CRYPTO_BlindingSecretP bks;
686 : const struct TALER_ExchangeBlindingValues *alg_values
687 9 : = TALER_denom_ewv_rsa_singleton ();
688 :
689 9 : TALER_planchet_master_setup_random (&ps);
690 9 : TALER_planchet_setup_coin_priv (&ps,
691 : alg_values,
692 : &coin_priv);
693 9 : TALER_planchet_blinding_secret_create (&ps,
694 : alg_values,
695 : &bks);
696 9 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
697 : &ach,
698 : sizeof(ach));
699 9 : duration = GNUNET_TIME_UNIT_ZERO;
700 9 : TALER_CRYPTO_helper_rsa_poll (dh);
701 18 : for (unsigned int j = 0; j<NUM_SIGN_PERFS;)
702 : {
703 9225 : for (unsigned int i = 0; i<MAX_KEYS; i++)
704 : {
705 9216 : if (! keys[i].valid)
706 9138 : continue;
707 78 : if (GNUNET_CRYPTO_BSA_RSA !=
708 78 : keys[i].denom_pub.bsign_pub_key->cipher)
709 0 : continue;
710 78 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
711 : keys[i].start_time.abs_time),
712 : >,
713 : GNUNET_TIME_UNIT_SECONDS))
714 69 : continue;
715 9 : if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
716 : keys[i].start_time.abs_time),
717 : >,
718 : keys[i].validity_duration))
719 0 : continue;
720 : {
721 : struct TALER_CoinPubHashP c_hash;
722 : struct TALER_PlanchetDetail pd;
723 :
724 9 : GNUNET_assert (GNUNET_YES ==
725 : TALER_planchet_prepare (&keys[i].denom_pub,
726 : alg_values,
727 : &bks,
728 : NULL,
729 : &coin_priv,
730 : &ach,
731 : &c_hash,
732 : &pd));
733 : /* use this key as long as it works */
734 : while (1)
735 891 : {
736 900 : struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get ();
737 : struct GNUNET_TIME_Relative delay;
738 900 : struct TALER_CRYPTO_RsaSignRequest rsr = {
739 900 : .h_rsa = &keys[i].h_rsa,
740 : .msg =
741 900 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
742 : blinded_msg,
743 : .msg_size =
744 900 : pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
745 : blinded_msg_size
746 : };
747 :
748 900 : ec = TALER_CRYPTO_helper_rsa_sign (dh,
749 : &rsr,
750 : &ds);
751 900 : if (TALER_EC_NONE != ec)
752 0 : break;
753 900 : delay = GNUNET_TIME_absolute_get_duration (start);
754 900 : duration = GNUNET_TIME_relative_add (duration,
755 : delay);
756 900 : TALER_blinded_denom_sig_free (&ds);
757 900 : j++;
758 900 : if (NUM_SIGN_PERFS <= j)
759 9 : break;
760 : }
761 9 : TALER_blinded_planchet_free (&pd.blinded_planchet);
762 : }
763 : } /* for i */
764 : } /* for j */
765 9 : fprintf (stderr,
766 : "%u (%s) signature operations took %s\n",
767 : (unsigned int) NUM_SIGN_PERFS,
768 : type,
769 : GNUNET_STRINGS_relative_time_to_string (duration,
770 : GNUNET_YES));
771 9 : return 0;
772 : }
773 :
774 :
775 : /**
776 : * Parallel signing logic.
777 : *
778 : * @param esh handle to the helper
779 : * @return 0 on success
780 : */
781 : static int
782 1 : par_signing (struct GNUNET_CONFIGURATION_Handle *cfg)
783 : {
784 : struct GNUNET_TIME_Absolute start;
785 : struct GNUNET_TIME_Relative duration;
786 : pid_t pids[NUM_CORES];
787 : struct TALER_CRYPTO_RsaDenominationHelper *dh;
788 :
789 1 : start = GNUNET_TIME_absolute_get ();
790 9 : for (unsigned int i = 0; i<NUM_CORES; i++)
791 : {
792 8 : pids[i] = fork ();
793 16 : num_keys = 0;
794 16 : GNUNET_assert (-1 != pids[i]);
795 16 : if (0 == pids[i])
796 : {
797 : int ret;
798 :
799 8 : dh = TALER_CRYPTO_helper_rsa_connect (cfg,
800 : "taler-exchange",
801 : &key_cb,
802 : NULL);
803 8 : GNUNET_assert (NULL != dh);
804 8 : ret = perf_signing (dh,
805 : "parallel");
806 8 : TALER_CRYPTO_helper_rsa_disconnect (dh);
807 8 : free_keys ();
808 8 : exit (ret);
809 : }
810 : }
811 9 : for (unsigned int i = 0; i<NUM_CORES; i++)
812 : {
813 : int wstatus;
814 :
815 8 : GNUNET_assert (pids[i] ==
816 : waitpid (pids[i],
817 : &wstatus,
818 : 0));
819 : }
820 1 : duration = GNUNET_TIME_absolute_get_duration (start);
821 1 : fprintf (stderr,
822 : "%u (parallel) signature operations took %s (total real time)\n",
823 : (unsigned int) NUM_SIGN_PERFS * NUM_CORES,
824 : GNUNET_STRINGS_relative_time_to_string (duration,
825 : GNUNET_YES));
826 1 : return 0;
827 : }
828 :
829 :
830 : /**
831 : * Main entry point into the test logic with the helper already running.
832 : */
833 : static int
834 1 : run_test (void)
835 : {
836 : struct GNUNET_CONFIGURATION_Handle *cfg;
837 : struct TALER_CRYPTO_RsaDenominationHelper *dh;
838 1 : struct timespec req = {
839 : .tv_nsec = 250000000
840 : };
841 : int ret;
842 :
843 1 : cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
844 1 : if (GNUNET_OK !=
845 1 : GNUNET_CONFIGURATION_load (cfg,
846 : "test_helper_rsa.conf"))
847 : {
848 0 : GNUNET_break (0);
849 0 : return 77;
850 : }
851 :
852 1 : fprintf (stderr,
853 : "Waiting for helper to start ... ");
854 1 : for (unsigned int i = 0; i<100; i++)
855 : {
856 1 : nanosleep (&req,
857 : NULL);
858 1 : dh = TALER_CRYPTO_helper_rsa_connect (cfg,
859 : "taler-exchange",
860 : &key_cb,
861 : NULL);
862 1 : if (NULL != dh)
863 1 : break;
864 0 : fprintf (stderr, ".");
865 : }
866 1 : if (NULL == dh)
867 : {
868 0 : fprintf (stderr,
869 : "\nFAILED: timeout trying to connect to helper\n");
870 0 : GNUNET_CONFIGURATION_destroy (cfg);
871 0 : return 1;
872 : }
873 1 : if (0 == num_keys)
874 : {
875 0 : fprintf (stderr,
876 : "\nFAILED: timeout trying to connect to helper\n");
877 0 : TALER_CRYPTO_helper_rsa_disconnect (dh);
878 0 : GNUNET_CONFIGURATION_destroy (cfg);
879 0 : return 1;
880 : }
881 1 : fprintf (stderr,
882 : " Done (%u keys)\n",
883 : num_keys);
884 1 : ret = 0;
885 1 : if (0 == ret)
886 1 : ret = test_revocation (dh);
887 1 : if (0 == ret)
888 1 : ret = test_signing (dh);
889 1 : if (0 == ret)
890 1 : ret = test_batch_signing (dh,
891 : 2,
892 : true);
893 1 : if (0 == ret)
894 1 : ret = test_batch_signing (dh,
895 : 64,
896 : true);
897 5 : for (unsigned int i = 0; i<4; i++)
898 : {
899 : static unsigned int batches[] = { 1, 4, 16, 64 };
900 4 : unsigned int batch_size = batches[i];
901 : struct GNUNET_TIME_Absolute start;
902 : struct GNUNET_TIME_Relative duration;
903 :
904 4 : start = GNUNET_TIME_absolute_get ();
905 4 : if (0 != ret)
906 0 : break;
907 4 : ret = test_batch_signing (dh,
908 : batch_size,
909 : false);
910 4 : duration = GNUNET_TIME_absolute_get_duration (start);
911 4 : fprintf (stderr,
912 : "%4u (batch) signature operations took %s (total real time)\n",
913 : (unsigned int) batch_size,
914 : GNUNET_STRINGS_relative_time_to_string (duration,
915 : GNUNET_YES));
916 : }
917 1 : if (0 == ret)
918 1 : ret = perf_signing (dh,
919 : "sequential");
920 1 : TALER_CRYPTO_helper_rsa_disconnect (dh);
921 1 : free_keys ();
922 1 : if (0 == ret)
923 1 : ret = par_signing (cfg);
924 : /* clean up our state */
925 1 : GNUNET_CONFIGURATION_destroy (cfg);
926 1 : return ret;
927 : }
928 :
929 :
930 : int
931 1 : main (int argc,
932 : const char *const argv[])
933 : {
934 : struct GNUNET_OS_Process *helper;
935 : char *libexec_dir;
936 : char *binary_name;
937 : int ret;
938 : enum GNUNET_OS_ProcessStatusType type;
939 : unsigned long code;
940 :
941 : (void) argc;
942 : (void) argv;
943 1 : unsetenv ("XDG_DATA_HOME");
944 1 : unsetenv ("XDG_CONFIG_HOME");
945 1 : GNUNET_log_setup ("test-helper-rsa",
946 : "WARNING",
947 : NULL);
948 1 : libexec_dir = GNUNET_OS_installation_get_path (TALER_EXCHANGE_project_data (),
949 : GNUNET_OS_IPK_BINDIR);
950 1 : GNUNET_asprintf (&binary_name,
951 : "%s/%s",
952 : libexec_dir,
953 : "taler-exchange-secmod-rsa");
954 1 : GNUNET_free (libexec_dir);
955 1 : helper = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
956 : NULL, NULL, NULL,
957 : binary_name,
958 : binary_name,
959 : "-c",
960 : "test_helper_rsa.conf",
961 : "-L",
962 : "WARNING",
963 : NULL);
964 1 : if (NULL == helper)
965 : {
966 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
967 : "exec",
968 : binary_name);
969 0 : GNUNET_free (binary_name);
970 0 : return 77;
971 : }
972 1 : GNUNET_free (binary_name);
973 1 : ret = run_test ();
974 :
975 1 : GNUNET_OS_process_kill (helper,
976 : SIGTERM);
977 1 : if (GNUNET_OK !=
978 1 : GNUNET_OS_process_wait_status (helper,
979 : &type,
980 : &code))
981 : {
982 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
983 : "Helper process did not die voluntarily, killing hard\n");
984 0 : GNUNET_OS_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_OS_process_destroy (helper);
998 1 : return ret;
999 : }
1000 :
1001 :
1002 : /* end of test_helper_rsa.c */
|