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