Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2024 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/secmod_rsa.c
18 : * @brief Standalone process to perform private key RSA operations
19 : * @author Christian Grothoff
20 : *
21 : * Key design points:
22 : * - EVERY thread of the exchange will have its own pair of connections to the
23 : * crypto helpers. This way, every thread will also have its own /keys state
24 : * and avoid the need to synchronize on those.
25 : * - auditor signatures and master signatures are to be kept in the exchange DB,
26 : * and merged with the public keys of the helper by the exchange HTTPD!
27 : * - the main loop of the helper is SINGLE-THREADED, but there are
28 : * threads for crypto-workers which do the signing in parallel, one per client.
29 : * - thread-safety: signing happens in parallel, thus when REMOVING private keys,
30 : * we must ensure that all signers are done before we fully free() the
31 : * private key. This is done by reference counting (as work is always
32 : * assigned and collected by the main thread).
33 : */
34 : #include "platform.h"
35 : #include "taler_util.h"
36 : #include "secmod_rsa.h"
37 : #include <gcrypt.h>
38 : #include <pthread.h>
39 : #include "taler_error_codes.h"
40 : #include "taler_signatures.h"
41 : #include "secmod_common.h"
42 : #include <poll.h>
43 :
44 :
45 : /**
46 : * Information we keep per denomination.
47 : */
48 : struct Denomination;
49 :
50 :
51 : /**
52 : * One particular denomination key.
53 : */
54 : struct DenominationKey
55 : {
56 :
57 : /**
58 : * Kept in a DLL of the respective denomination. Sorted by anchor time.
59 : */
60 : struct DenominationKey *next;
61 :
62 : /**
63 : * Kept in a DLL of the respective denomination. Sorted by anchor time.
64 : */
65 : struct DenominationKey *prev;
66 :
67 : /**
68 : * Denomination this key belongs to.
69 : */
70 : struct Denomination *denom;
71 :
72 : /**
73 : * Name of the file this key is stored under.
74 : */
75 : char *filename;
76 :
77 : /**
78 : * The private key of the denomination.
79 : */
80 : struct GNUNET_CRYPTO_RsaPrivateKey *denom_priv;
81 :
82 : /**
83 : * The public key of the denomination.
84 : */
85 : struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
86 :
87 : /**
88 : * Message to transmit to clients to introduce this public key.
89 : */
90 : struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
91 :
92 : /**
93 : * Hash of this denomination's public key.
94 : */
95 : struct TALER_RsaPubHashP h_rsa;
96 :
97 : /**
98 : * Time at which this key is supposed to become valid.
99 : */
100 : struct GNUNET_TIME_Timestamp anchor;
101 :
102 : /**
103 : * Generation when this key was created or revoked.
104 : */
105 : uint64_t key_gen;
106 :
107 : /**
108 : * Reference counter. Counts the number of threads that are
109 : * using this key at this time.
110 : */
111 : unsigned int rc;
112 :
113 : /**
114 : * Flag set to true if this key has been purged and the memory
115 : * must be freed as soon as @e rc hits zero.
116 : */
117 : bool purge;
118 :
119 : };
120 :
121 :
122 : struct Denomination
123 : {
124 :
125 : /**
126 : * Kept in a DLL. Sorted by #denomination_action_time().
127 : */
128 : struct Denomination *next;
129 :
130 : /**
131 : * Kept in a DLL. Sorted by #denomination_action_time().
132 : */
133 : struct Denomination *prev;
134 :
135 : /**
136 : * Head of DLL of actual keys of this denomination.
137 : */
138 : struct DenominationKey *keys_head;
139 :
140 : /**
141 : * Tail of DLL of actual keys of this denomination.
142 : */
143 : struct DenominationKey *keys_tail;
144 :
145 : /**
146 : * How long can coins be withdrawn (generated)? Should be small
147 : * enough to limit how many coins will be signed into existence with
148 : * the same key, but large enough to still provide a reasonable
149 : * anonymity set.
150 : */
151 : struct GNUNET_TIME_Relative duration_withdraw;
152 :
153 : /**
154 : * What is the configuration section of this denomination type? Also used
155 : * for the directory name where the denomination keys are stored.
156 : */
157 : char *section;
158 :
159 : /**
160 : * Length of (new) RSA keys (in bits).
161 : */
162 : uint32_t rsa_keysize;
163 : };
164 :
165 :
166 : /**
167 : * A semaphore.
168 : */
169 : struct Semaphore
170 : {
171 : /**
172 : * Mutex for the semaphore.
173 : */
174 : pthread_mutex_t mutex;
175 :
176 : /**
177 : * Condition variable for the semaphore.
178 : */
179 : pthread_cond_t cv;
180 :
181 : /**
182 : * Counter of the semaphore.
183 : */
184 : unsigned int ctr;
185 : };
186 :
187 :
188 : /**
189 : * Job in a batch sign request.
190 : */
191 : struct BatchJob;
192 :
193 : /**
194 : * Handle for a thread that does work in batch signing.
195 : */
196 : struct Worker
197 : {
198 : /**
199 : * Kept in a DLL.
200 : */
201 : struct Worker *prev;
202 :
203 : /**
204 : * Kept in a DLL.
205 : */
206 : struct Worker *next;
207 :
208 : /**
209 : * Job this worker should do next.
210 : */
211 : struct BatchJob *job;
212 :
213 : /**
214 : * Semaphore to signal the worker that a job is available.
215 : */
216 : struct Semaphore sem;
217 :
218 : /**
219 : * Handle for this thread.
220 : */
221 : pthread_t pt;
222 :
223 : /**
224 : * Set to true if the worker should terminate.
225 : */
226 : bool do_shutdown;
227 : };
228 :
229 :
230 : /**
231 : * Job in a batch sign request.
232 : */
233 : struct BatchJob
234 : {
235 : /**
236 : * Request we are working on.
237 : */
238 : const struct TALER_CRYPTO_SignRequest *sr;
239 :
240 : /**
241 : * Thread doing the work.
242 : */
243 : struct Worker *worker;
244 :
245 : /**
246 : * Result with the signature.
247 : */
248 : struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
249 :
250 : /**
251 : * Semaphore to signal that the job is finished.
252 : */
253 : struct Semaphore sem;
254 :
255 : /**
256 : * Computation status.
257 : */
258 : enum TALER_ErrorCode ec;
259 :
260 : };
261 :
262 :
263 : /**
264 : * Head of DLL of workers ready for more work.
265 : */
266 : static struct Worker *worker_head;
267 :
268 : /**
269 : * Tail of DLL of workers ready for more work.
270 : */
271 : static struct Worker *worker_tail;
272 :
273 : /**
274 : * Lock for manipulating the worker DLL.
275 : */
276 : static pthread_mutex_t worker_lock;
277 :
278 : /**
279 : * Total number of workers that were started.
280 : */
281 : static unsigned int workers;
282 :
283 : /**
284 : * Semaphore used to grab a worker.
285 : */
286 : static struct Semaphore worker_sem;
287 :
288 : /**
289 : * Command-line options for various TALER_SECMOD_XXX_run() functions.
290 : */
291 : static struct TALER_SECMOD_Options *globals;
292 :
293 : /**
294 : * Where do we store the keys?
295 : */
296 : static char *keydir;
297 :
298 : /**
299 : * How much should coin creation (@e duration_withdraw) duration overlap
300 : * with the next denomination? Basically, the starting time of two
301 : * denominations is always @e duration_withdraw - #overlap_duration apart.
302 : */
303 : static struct GNUNET_TIME_Relative overlap_duration;
304 :
305 : /**
306 : * How long into the future do we pre-generate keys?
307 : */
308 : static struct GNUNET_TIME_Relative lookahead_sign;
309 :
310 : /**
311 : * All of our denominations, in a DLL. Sorted?
312 : */
313 : static struct Denomination *denom_head;
314 :
315 : /**
316 : * All of our denominations, in a DLL. Sorted?
317 : */
318 : static struct Denomination *denom_tail;
319 :
320 : /**
321 : * Map of hashes of public (RSA) keys to `struct DenominationKey *`
322 : * with the respective private keys.
323 : */
324 : static struct GNUNET_CONTAINER_MultiHashMap *keys;
325 :
326 : /**
327 : * Task run to generate new keys.
328 : */
329 : static struct GNUNET_SCHEDULER_Task *keygen_task;
330 :
331 : /**
332 : * Lock for the keys queue.
333 : */
334 : static pthread_mutex_t keys_lock;
335 :
336 : /**
337 : * Current key generation.
338 : */
339 : static uint64_t key_gen;
340 :
341 :
342 : /**
343 : * Generate the announcement message for @a dk.
344 : *
345 : * @param[in,out] dk denomination key to generate the announcement for
346 : */
347 : static void
348 3568 : generate_response (struct DenominationKey *dk)
349 : {
350 3568 : struct Denomination *denom = dk->denom;
351 3568 : size_t nlen = strlen (denom->section) + 1;
352 : struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
353 : size_t buf_len;
354 : void *buf;
355 : void *p;
356 : size_t tlen;
357 :
358 3568 : buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub,
359 : &buf);
360 3568 : GNUNET_assert (buf_len < UINT16_MAX);
361 3568 : GNUNET_assert (nlen < UINT16_MAX);
362 3568 : tlen = buf_len + nlen + sizeof (*an);
363 3568 : GNUNET_assert (tlen < UINT16_MAX);
364 3568 : an = GNUNET_malloc (tlen);
365 3568 : an->header.size = htons ((uint16_t) tlen);
366 3568 : an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
367 3568 : an->pub_size = htons ((uint16_t) buf_len);
368 3568 : an->section_name_len = htons ((uint16_t) nlen);
369 3568 : an->anchor_time = GNUNET_TIME_timestamp_hton (dk->anchor);
370 3568 : an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw);
371 3568 : TALER_exchange_secmod_rsa_sign (&dk->h_rsa,
372 3568 : denom->section,
373 : dk->anchor,
374 : denom->duration_withdraw,
375 : &TES_smpriv,
376 : &an->secm_sig);
377 3568 : an->secm_pub = TES_smpub;
378 3568 : p = (void *) &an[1];
379 3568 : GNUNET_memcpy (p,
380 : buf,
381 : buf_len);
382 3568 : GNUNET_free (buf);
383 3568 : GNUNET_memcpy (p + buf_len,
384 : denom->section,
385 : nlen);
386 3568 : dk->an = an;
387 3568 : }
388 :
389 :
390 : /**
391 : * Do the actual signing work.
392 : *
393 : * @param h_rsa key to sign with
394 : * @param bm blinded message to sign
395 : * @param[out] rsa_signaturep set to the RSA signature
396 : * @return #TALER_EC_NONE on success
397 : */
398 : static enum TALER_ErrorCode
399 1604 : do_sign (const struct TALER_RsaPubHashP *h_rsa,
400 : const struct GNUNET_CRYPTO_RsaBlindedMessage *bm,
401 : struct GNUNET_CRYPTO_RsaSignature **rsa_signaturep)
402 : {
403 : struct DenominationKey *dk;
404 : struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
405 1604 : struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
406 :
407 1592 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
408 1630 : dk = GNUNET_CONTAINER_multihashmap_get (keys,
409 : &h_rsa->hash);
410 1630 : if (NULL == dk)
411 : {
412 3 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
413 3 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
414 : "Signing request failed, denomination key %s unknown\n",
415 : GNUNET_h2s (&h_rsa->hash));
416 3 : return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
417 : }
418 1627 : if (GNUNET_TIME_absolute_is_future (dk->anchor.abs_time))
419 : {
420 : /* it is too early */
421 335 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
422 334 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
423 : "Signing request failed, denomination key %s is not yet valid\n",
424 : GNUNET_h2s (&h_rsa->hash));
425 334 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY;
426 : }
427 :
428 1292 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
429 : "Received request to sign over %u bytes with key %s\n",
430 : (unsigned int) bm->blinded_msg_size,
431 : GNUNET_h2s (&h_rsa->hash));
432 1292 : GNUNET_assert (dk->rc < UINT_MAX);
433 1292 : dk->rc++;
434 1292 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
435 : rsa_signature
436 1292 : = GNUNET_CRYPTO_rsa_sign_blinded (dk->denom_priv,
437 : bm);
438 1292 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
439 1292 : GNUNET_assert (dk->rc > 0);
440 1292 : dk->rc--;
441 1292 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
442 1292 : if (NULL == rsa_signature)
443 : {
444 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
445 : "Signing request failed, worker failed to produce signature\n");
446 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
447 : }
448 :
449 1292 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
450 : "Sending RSA signature after %s\n",
451 : GNUNET_TIME_relative2s (
452 : GNUNET_TIME_absolute_get_duration (now),
453 : GNUNET_YES));
454 1292 : *rsa_signaturep = rsa_signature;
455 1292 : return TALER_EC_NONE;
456 : }
457 :
458 :
459 : /**
460 : * Generate error response that signing failed.
461 : *
462 : * @param client client to send response to
463 : * @param ec error code to include
464 : * @return #GNUNET_OK on success
465 : */
466 : static enum GNUNET_GenericReturnValue
467 338 : fail_sign (struct TES_Client *client,
468 : enum TALER_ErrorCode ec)
469 : {
470 338 : struct TALER_CRYPTO_SignFailure sf = {
471 338 : .header.size = htons (sizeof (sf)),
472 338 : .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
473 338 : .ec = htonl (ec)
474 : };
475 :
476 338 : return TES_transmit (client->csock,
477 : &sf.header);
478 : }
479 :
480 :
481 : /**
482 : * Generate signature response.
483 : *
484 : * @param client client to send response to
485 : * @param[in] rsa_signature signature to send, freed by this function
486 : * @return #GNUNET_OK on success
487 : */
488 : static enum GNUNET_GenericReturnValue
489 1292 : send_signature (struct TES_Client *client,
490 : struct GNUNET_CRYPTO_RsaSignature *rsa_signature)
491 : {
492 : struct TALER_CRYPTO_SignResponse *sr;
493 : void *buf;
494 : size_t buf_size;
495 : size_t tsize;
496 : enum GNUNET_GenericReturnValue ret;
497 :
498 1292 : buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature,
499 : &buf);
500 1292 : GNUNET_CRYPTO_rsa_signature_free (rsa_signature);
501 1292 : tsize = sizeof (*sr) + buf_size;
502 1292 : GNUNET_assert (tsize < UINT16_MAX);
503 1292 : sr = GNUNET_malloc (tsize);
504 1292 : sr->header.size = htons (tsize);
505 1292 : sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
506 1292 : GNUNET_memcpy (&sr[1],
507 : buf,
508 : buf_size);
509 1292 : GNUNET_free (buf);
510 1292 : ret = TES_transmit (client->csock,
511 1292 : &sr->header);
512 1292 : GNUNET_free (sr);
513 1292 : return ret;
514 : }
515 :
516 :
517 : /**
518 : * Handle @a client request @a sr to create signature. Create the
519 : * signature using the respective key and return the result to
520 : * the client.
521 : *
522 : * @param client the client making the request
523 : * @param sr the request details
524 : * @return #GNUNET_OK on success
525 : */
526 : static enum GNUNET_GenericReturnValue
527 907 : handle_sign_request (struct TES_Client *client,
528 : const struct TALER_CRYPTO_SignRequest *sr)
529 : {
530 907 : struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
531 907 : .blinded_msg = (void *) &sr[1],
532 907 : .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
533 : };
534 : struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
535 : enum TALER_ErrorCode ec;
536 :
537 907 : ec = do_sign (&sr->h_rsa,
538 : &bm,
539 : &rsa_signature);
540 907 : if (TALER_EC_NONE != ec)
541 : {
542 6 : return fail_sign (client,
543 : ec);
544 : }
545 901 : return send_signature (client,
546 : rsa_signature);
547 : }
548 :
549 :
550 : /**
551 : * Initialize a semaphore @a sem with a value of @a val.
552 : *
553 : * @param[out] sem semaphore to initialize
554 : * @param val initial value of the semaphore
555 : */
556 : static void
557 1063 : sem_init (struct Semaphore *sem,
558 : unsigned int val)
559 : {
560 1063 : GNUNET_assert (0 ==
561 : pthread_mutex_init (&sem->mutex,
562 : NULL));
563 1063 : GNUNET_assert (0 ==
564 : pthread_cond_init (&sem->cv,
565 : NULL));
566 1063 : sem->ctr = val;
567 1063 : }
568 :
569 :
570 : /**
571 : * Decrement semaphore, blocks until this is possible.
572 : *
573 : * @param[in,out] sem semaphore to decrement
574 : */
575 : static void
576 2798 : sem_down (struct Semaphore *sem)
577 : {
578 2798 : GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
579 4024 : while (0 == sem->ctr)
580 : {
581 1237 : pthread_cond_wait (&sem->cv,
582 : &sem->mutex);
583 : }
584 2787 : sem->ctr--;
585 2787 : GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
586 2770 : }
587 :
588 :
589 : /**
590 : * Increment semaphore, blocks until this is possible.
591 : *
592 : * @param[in,out] sem semaphore to decrement
593 : */
594 : static void
595 2791 : sem_up (struct Semaphore *sem)
596 : {
597 2791 : GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
598 2809 : sem->ctr++;
599 2809 : GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
600 2805 : pthread_cond_signal (&sem->cv);
601 2798 : }
602 :
603 :
604 : /**
605 : * Release resources used by @a sem.
606 : *
607 : * @param[in] sem semaphore to release (except the memory itself)
608 : */
609 : static void
610 1063 : sem_done (struct Semaphore *sem)
611 : {
612 1063 : GNUNET_break (0 == pthread_cond_destroy (&sem->cv));
613 1063 : GNUNET_break (0 == pthread_mutex_destroy (&sem->mutex));
614 1063 : }
615 :
616 :
617 : /**
618 : * Main logic of a worker thread. Grabs work, does it,
619 : * grabs more work.
620 : *
621 : * @param cls a `struct Worker *`
622 : * @returns cls
623 : */
624 : static void *
625 320 : worker (void *cls)
626 : {
627 320 : struct Worker *w = cls;
628 :
629 : while (true)
630 : {
631 1040 : GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
632 1043 : GNUNET_CONTAINER_DLL_insert (worker_head,
633 : worker_tail,
634 : w);
635 1043 : GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
636 1040 : sem_up (&worker_sem);
637 1041 : sem_down (&w->sem);
638 1021 : if (w->do_shutdown)
639 320 : break;
640 : {
641 701 : struct BatchJob *bj = w->job;
642 701 : const struct TALER_CRYPTO_SignRequest *sr = bj->sr;
643 701 : struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
644 701 : .blinded_msg = (void *) &sr[1],
645 701 : .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
646 : };
647 :
648 701 : bj->ec = do_sign (&sr->h_rsa,
649 : &bm,
650 : &bj->rsa_signature);
651 721 : sem_up (&bj->sem);
652 720 : w->job = NULL;
653 : }
654 : }
655 320 : return w;
656 : }
657 :
658 :
659 : /**
660 : * Start batch job @a bj to sign @a sr.
661 : *
662 : * @param sr signature request to answer
663 : * @param[out] bj job data structure
664 : */
665 : static void
666 723 : start_job (const struct TALER_CRYPTO_SignRequest *sr,
667 : struct BatchJob *bj)
668 : {
669 723 : sem_init (&bj->sem,
670 : 0);
671 723 : bj->sr = sr;
672 723 : sem_down (&worker_sem);
673 723 : GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
674 723 : bj->worker = worker_head;
675 723 : GNUNET_CONTAINER_DLL_remove (worker_head,
676 : worker_tail,
677 : bj->worker);
678 723 : GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
679 723 : bj->worker->job = bj;
680 723 : sem_up (&bj->worker->sem);
681 723 : }
682 :
683 :
684 : /**
685 : * Finish a job @a bj for a @a client.
686 : *
687 : * @param client who made the request
688 : * @param[in,out] bj job to finish
689 : */
690 : static void
691 723 : finish_job (struct TES_Client *client,
692 : struct BatchJob *bj)
693 : {
694 723 : sem_down (&bj->sem);
695 723 : sem_done (&bj->sem);
696 723 : if (TALER_EC_NONE != bj->ec)
697 : {
698 332 : fail_sign (client,
699 : bj->ec);
700 332 : return;
701 : }
702 391 : GNUNET_assert (NULL != bj->rsa_signature);
703 391 : send_signature (client,
704 : bj->rsa_signature);
705 391 : bj->rsa_signature = NULL; /* freed in send_signature */
706 : }
707 :
708 :
709 : /**
710 : * Handle @a client request @a sr to create a batch of signature. Creates the
711 : * signatures using the respective key and return the results to the client.
712 : *
713 : * @param client the client making the request
714 : * @param bsr the request details
715 : * @return #GNUNET_OK on success
716 : */
717 : static enum GNUNET_GenericReturnValue
718 82 : handle_batch_sign_request (struct TES_Client *client,
719 : const struct TALER_CRYPTO_BatchSignRequest *bsr)
720 82 : {
721 82 : uint32_t bs = ntohl (bsr->batch_size);
722 82 : uint16_t size = ntohs (bsr->header.size) - sizeof (*bsr);
723 82 : const void *off = (const void *) &bsr[1];
724 82 : unsigned int idx = 0;
725 82 : struct BatchJob jobs[bs];
726 82 : bool failure = false;
727 :
728 82 : if (bs > TALER_MAX_COINS)
729 : {
730 0 : GNUNET_break_op (0);
731 0 : return GNUNET_SYSERR;
732 : }
733 805 : while ( (bs > 0) &&
734 : (size > sizeof (struct TALER_CRYPTO_SignRequest)) )
735 : {
736 723 : const struct TALER_CRYPTO_SignRequest *sr = off;
737 723 : uint16_t s = ntohs (sr->header.size);
738 :
739 723 : if (s > size)
740 : {
741 0 : failure = true;
742 0 : bs = idx;
743 0 : break;
744 : }
745 723 : start_job (sr,
746 723 : &jobs[idx++]);
747 723 : off += s;
748 723 : size -= s;
749 : }
750 82 : GNUNET_break_op (0 == size);
751 82 : bs = GNUNET_MIN (bs,
752 : idx);
753 805 : for (unsigned int i = 0; i<bs; i++)
754 723 : finish_job (client,
755 : &jobs[i]);
756 82 : if (failure)
757 : {
758 0 : struct TALER_CRYPTO_SignFailure sf = {
759 0 : .header.size = htons (sizeof (sf)),
760 0 : .header.type = htons (TALER_HELPER_RSA_MT_RES_BATCH_FAILURE),
761 0 : .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
762 : };
763 :
764 0 : GNUNET_break (0);
765 0 : return TES_transmit (client->csock,
766 : &sf.header);
767 : }
768 82 : return GNUNET_OK;
769 : }
770 :
771 :
772 : /**
773 : * Start worker thread for batch processing.
774 : *
775 : * @return #GNUNET_OK on success
776 : */
777 : static enum GNUNET_GenericReturnValue
778 320 : start_worker (void)
779 : {
780 : struct Worker *w;
781 :
782 320 : w = GNUNET_new (struct Worker);
783 320 : sem_init (&w->sem,
784 : 0);
785 320 : if (0 != pthread_create (&w->pt,
786 : NULL,
787 : &worker,
788 : w))
789 : {
790 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
791 : "pthread_create");
792 0 : GNUNET_free (w);
793 0 : return GNUNET_SYSERR;
794 : }
795 320 : workers++;
796 320 : return GNUNET_OK;
797 : }
798 :
799 :
800 : /**
801 : * Stop all worker threads.
802 : */
803 : static void
804 20 : stop_workers (void)
805 : {
806 340 : while (workers > 0)
807 : {
808 : struct Worker *w;
809 : void *result;
810 :
811 320 : sem_down (&worker_sem);
812 320 : GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
813 320 : w = worker_head;
814 320 : GNUNET_CONTAINER_DLL_remove (worker_head,
815 : worker_tail,
816 : w);
817 320 : GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
818 320 : w->do_shutdown = true;
819 320 : sem_up (&w->sem);
820 320 : pthread_join (w->pt,
821 : &result);
822 320 : GNUNET_assert (result == w);
823 320 : sem_done (&w->sem);
824 320 : GNUNET_free (w);
825 320 : workers--;
826 : }
827 20 : }
828 :
829 :
830 : /**
831 : * Initialize key material for denomination key @a dk (also on disk).
832 : *
833 : * @param[in,out] dk denomination key to compute key material for
834 : * @param position where in the DLL will the @a dk go
835 : * @return #GNUNET_OK on success
836 : */
837 : static enum GNUNET_GenericReturnValue
838 3144 : setup_key (struct DenominationKey *dk,
839 : struct DenominationKey *position)
840 : {
841 3144 : struct Denomination *denom = dk->denom;
842 : struct GNUNET_CRYPTO_RsaPrivateKey *priv;
843 : struct GNUNET_CRYPTO_RsaPublicKey *pub;
844 : size_t buf_size;
845 : void *buf;
846 :
847 3144 : priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize);
848 3144 : if (NULL == priv)
849 : {
850 0 : GNUNET_break (0);
851 0 : GNUNET_SCHEDULER_shutdown ();
852 0 : globals->global_ret = EXIT_FAILURE;
853 0 : return GNUNET_SYSERR;
854 : }
855 3144 : pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
856 3144 : if (NULL == pub)
857 : {
858 0 : GNUNET_break (0);
859 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
860 0 : return GNUNET_SYSERR;
861 : }
862 3144 : buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
863 : &buf);
864 3144 : GNUNET_CRYPTO_rsa_public_key_hash (pub,
865 : &dk->h_rsa.hash);
866 3144 : GNUNET_asprintf (&dk->filename,
867 : "%s/%s/%llu",
868 : keydir,
869 : denom->section,
870 3144 : (unsigned long long) (dk->anchor.abs_time.abs_value_us
871 3144 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us
872 : ));
873 3144 : if (GNUNET_OK !=
874 3144 : GNUNET_DISK_fn_write (dk->filename,
875 : buf,
876 : buf_size,
877 : GNUNET_DISK_PERM_USER_READ))
878 : {
879 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
880 : "write",
881 : dk->filename);
882 0 : GNUNET_free (buf);
883 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
884 0 : GNUNET_CRYPTO_rsa_public_key_free (pub);
885 0 : return GNUNET_SYSERR;
886 : }
887 3144 : GNUNET_free (buf);
888 3144 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
889 : "Setup fresh private key %s at %s in `%s' (generation #%llu)\n",
890 : GNUNET_h2s (&dk->h_rsa.hash),
891 : GNUNET_TIME_timestamp2s (dk->anchor),
892 : dk->filename,
893 : (unsigned long long) key_gen);
894 3144 : dk->denom_priv = priv;
895 3144 : dk->denom_pub = pub;
896 3144 : dk->key_gen = key_gen;
897 3144 : generate_response (dk);
898 3144 : if (GNUNET_OK !=
899 3144 : GNUNET_CONTAINER_multihashmap_put (
900 : keys,
901 3144 : &dk->h_rsa.hash,
902 : dk,
903 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
904 : {
905 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
906 : "Duplicate private key created! Terminating.\n");
907 0 : GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
908 0 : GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
909 0 : GNUNET_free (dk->filename);
910 0 : GNUNET_free (dk->an);
911 0 : GNUNET_free (dk);
912 0 : return GNUNET_SYSERR;
913 : }
914 3144 : GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
915 : denom->keys_tail,
916 : position,
917 : dk);
918 3144 : return GNUNET_OK;
919 : }
920 :
921 :
922 : /**
923 : * The withdraw period of a key @a dk has expired. Purge it.
924 : *
925 : * @param[in] dk expired denomination key to purge
926 : */
927 : static void
928 3 : purge_key (struct DenominationKey *dk)
929 : {
930 3 : if (dk->purge)
931 0 : return;
932 3 : if (0 != unlink (dk->filename))
933 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
934 : "unlink",
935 : dk->filename);
936 3 : GNUNET_free (dk->filename);
937 3 : dk->purge = true;
938 3 : dk->key_gen = key_gen;
939 : }
940 :
941 :
942 : /**
943 : * A @a client informs us that a key has been revoked.
944 : * Check if the key is still in use, and if so replace (!)
945 : * it with a fresh key.
946 : *
947 : * @param client the client making the request
948 : * @param rr the revocation request
949 : */
950 : static enum GNUNET_GenericReturnValue
951 3 : handle_revoke_request (struct TES_Client *client,
952 : const struct TALER_CRYPTO_RevokeRequest *rr)
953 : {
954 : struct DenominationKey *dk;
955 : struct DenominationKey *ndk;
956 : struct Denomination *denom;
957 :
958 : (void) client;
959 3 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
960 3 : dk = GNUNET_CONTAINER_multihashmap_get (keys,
961 : &rr->h_rsa.hash);
962 3 : if (NULL == dk)
963 : {
964 0 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
965 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
966 : "Revocation request ignored, denomination key %s unknown\n",
967 : GNUNET_h2s (&rr->h_rsa.hash));
968 0 : return GNUNET_OK;
969 : }
970 3 : if (dk->purge)
971 : {
972 0 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
973 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
974 : "Revocation request ignored, denomination key %s already revoked\n",
975 : GNUNET_h2s (&rr->h_rsa.hash));
976 0 : return GNUNET_OK;
977 : }
978 :
979 3 : key_gen++;
980 3 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
981 : "Revoking key %s, bumping generation to %llu\n",
982 : GNUNET_h2s (&rr->h_rsa.hash),
983 : (unsigned long long) key_gen);
984 3 : purge_key (dk);
985 :
986 : /* Setup replacement key */
987 3 : denom = dk->denom;
988 3 : ndk = GNUNET_new (struct DenominationKey);
989 3 : ndk->denom = denom;
990 3 : ndk->anchor = dk->anchor;
991 3 : if (GNUNET_OK !=
992 3 : setup_key (ndk,
993 : dk))
994 : {
995 0 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
996 0 : GNUNET_break (0);
997 0 : GNUNET_SCHEDULER_shutdown ();
998 0 : globals->global_ret = EXIT_FAILURE;
999 0 : return GNUNET_SYSERR;
1000 : }
1001 3 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1002 3 : TES_wake_clients ();
1003 3 : return GNUNET_OK;
1004 : }
1005 :
1006 :
1007 : /**
1008 : * Handle @a hdr message received from @a client.
1009 : *
1010 : * @param client the client that received the message
1011 : * @param hdr message that was received
1012 : * @return #GNUNET_OK on success
1013 : */
1014 : static enum GNUNET_GenericReturnValue
1015 992 : rsa_work_dispatch (struct TES_Client *client,
1016 : const struct GNUNET_MessageHeader *hdr)
1017 : {
1018 992 : uint16_t msize = ntohs (hdr->size);
1019 :
1020 992 : switch (ntohs (hdr->type))
1021 : {
1022 907 : case TALER_HELPER_RSA_MT_REQ_SIGN:
1023 907 : if (msize <= sizeof (struct TALER_CRYPTO_SignRequest))
1024 : {
1025 0 : GNUNET_break_op (0);
1026 0 : return GNUNET_SYSERR;
1027 : }
1028 907 : return handle_sign_request (
1029 : client,
1030 : (const struct TALER_CRYPTO_SignRequest *) hdr);
1031 3 : case TALER_HELPER_RSA_MT_REQ_REVOKE:
1032 3 : if (msize != sizeof (struct TALER_CRYPTO_RevokeRequest))
1033 : {
1034 0 : GNUNET_break_op (0);
1035 0 : return GNUNET_SYSERR;
1036 : }
1037 3 : return handle_revoke_request (
1038 : client,
1039 : (const struct TALER_CRYPTO_RevokeRequest *) hdr);
1040 82 : case TALER_HELPER_RSA_MT_REQ_BATCH_SIGN:
1041 82 : if (msize <= sizeof (struct TALER_CRYPTO_BatchSignRequest))
1042 : {
1043 0 : GNUNET_break_op (0);
1044 0 : return GNUNET_SYSERR;
1045 : }
1046 82 : return handle_batch_sign_request (
1047 : client,
1048 : (const struct TALER_CRYPTO_BatchSignRequest *) hdr);
1049 0 : default:
1050 0 : GNUNET_break_op (0);
1051 0 : return GNUNET_SYSERR;
1052 : }
1053 : }
1054 :
1055 :
1056 : /**
1057 : * Send our initial key set to @a client together with the
1058 : * "sync" terminator.
1059 : *
1060 : * @param client the client to inform
1061 : * @return #GNUNET_OK on success
1062 : */
1063 : static enum GNUNET_GenericReturnValue
1064 38 : rsa_client_init (struct TES_Client *client)
1065 : {
1066 38 : size_t obs = 0;
1067 : char *buf;
1068 :
1069 38 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1070 : "Initializing new client %p\n",
1071 : client);
1072 38 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1073 38 : for (struct Denomination *denom = denom_head;
1074 207 : NULL != denom;
1075 169 : denom = denom->next)
1076 : {
1077 169 : for (struct DenominationKey *dk = denom->keys_head;
1078 8045 : NULL != dk;
1079 7876 : dk = dk->next)
1080 : {
1081 7876 : GNUNET_assert (obs + ntohs (dk->an->header.size)
1082 : > obs);
1083 7876 : obs += ntohs (dk->an->header.size);
1084 : }
1085 : }
1086 38 : buf = GNUNET_malloc (obs);
1087 38 : obs = 0;
1088 38 : for (struct Denomination *denom = denom_head;
1089 207 : NULL != denom;
1090 169 : denom = denom->next)
1091 : {
1092 169 : for (struct DenominationKey *dk = denom->keys_head;
1093 8045 : NULL != dk;
1094 7876 : dk = dk->next)
1095 : {
1096 7876 : GNUNET_memcpy (&buf[obs],
1097 : dk->an,
1098 : ntohs (dk->an->header.size));
1099 7876 : GNUNET_assert (obs + ntohs (dk->an->header.size)
1100 : > obs);
1101 7876 : obs += ntohs (dk->an->header.size);
1102 : }
1103 : }
1104 38 : client->key_gen = key_gen;
1105 38 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1106 38 : if (GNUNET_OK !=
1107 38 : TES_transmit_raw (client->csock,
1108 : obs,
1109 : buf))
1110 : {
1111 0 : GNUNET_free (buf);
1112 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1113 : "Client %p must have disconnected\n",
1114 : client);
1115 0 : return GNUNET_SYSERR;
1116 : }
1117 38 : GNUNET_free (buf);
1118 : {
1119 38 : struct GNUNET_MessageHeader synced = {
1120 38 : .type = htons (TALER_HELPER_RSA_SYNCED),
1121 38 : .size = htons (sizeof (synced))
1122 : };
1123 :
1124 38 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1125 : "Sending RSA SYNCED message to %p\n",
1126 : client);
1127 38 : if (GNUNET_OK !=
1128 38 : TES_transmit (client->csock,
1129 : &synced))
1130 : {
1131 0 : GNUNET_break (0);
1132 0 : return GNUNET_SYSERR;
1133 : }
1134 : }
1135 38 : return GNUNET_OK;
1136 : }
1137 :
1138 :
1139 : /**
1140 : * Notify @a client about all changes to the keys since
1141 : * the last generation known to the @a client.
1142 : *
1143 : * @param client the client to notify
1144 : * @return #GNUNET_OK on success
1145 : */
1146 : static enum GNUNET_GenericReturnValue
1147 22 : rsa_update_client_keys (struct TES_Client *client)
1148 : {
1149 22 : size_t obs = 0;
1150 : char *buf;
1151 : enum GNUNET_GenericReturnValue ret;
1152 :
1153 22 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1154 22 : for (struct Denomination *denom = denom_head;
1155 106 : NULL != denom;
1156 84 : denom = denom->next)
1157 : {
1158 84 : for (struct DenominationKey *key = denom->keys_head;
1159 3673 : NULL != key;
1160 3589 : key = key->next)
1161 : {
1162 3589 : if (key->key_gen <= client->key_gen)
1163 3582 : continue;
1164 7 : if (key->purge)
1165 3 : obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
1166 : else
1167 4 : obs += ntohs (key->an->header.size);
1168 : }
1169 : }
1170 22 : if (0 == obs)
1171 : {
1172 : /* nothing to do */
1173 18 : client->key_gen = key_gen;
1174 18 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1175 18 : return GNUNET_OK;
1176 : }
1177 4 : buf = GNUNET_malloc (obs);
1178 4 : obs = 0;
1179 4 : for (struct Denomination *denom = denom_head;
1180 8 : NULL != denom;
1181 4 : denom = denom->next)
1182 : {
1183 4 : for (struct DenominationKey *key = denom->keys_head;
1184 35 : NULL != key;
1185 31 : key = key->next)
1186 : {
1187 31 : if (key->key_gen <= client->key_gen)
1188 24 : continue;
1189 7 : if (key->purge)
1190 : {
1191 3 : struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
1192 3 : .header.type = htons (TALER_HELPER_RSA_MT_PURGE),
1193 3 : .header.size = htons (sizeof (pn)),
1194 : .h_rsa = key->h_rsa
1195 : };
1196 :
1197 3 : GNUNET_memcpy (&buf[obs],
1198 : &pn,
1199 : sizeof (pn));
1200 3 : GNUNET_assert (obs + sizeof (pn)
1201 : > obs);
1202 3 : obs += sizeof (pn);
1203 : }
1204 : else
1205 : {
1206 4 : GNUNET_memcpy (&buf[obs],
1207 : key->an,
1208 : ntohs (key->an->header.size));
1209 4 : GNUNET_assert (obs + ntohs (key->an->header.size)
1210 : > obs);
1211 4 : obs += ntohs (key->an->header.size);
1212 : }
1213 : }
1214 : }
1215 4 : client->key_gen = key_gen;
1216 4 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1217 4 : ret = TES_transmit_raw (client->csock,
1218 : obs,
1219 : buf);
1220 4 : GNUNET_free (buf);
1221 4 : return ret;
1222 : }
1223 :
1224 :
1225 : /**
1226 : * Create a new denomination key (we do not have enough).
1227 : *
1228 : * @param[in] denom denomination key to create
1229 : * @param now current time to use (to get many keys to use the exact same time)
1230 : * @return #GNUNET_OK on success
1231 : */
1232 : static enum GNUNET_GenericReturnValue
1233 3141 : create_key (struct Denomination *denom,
1234 : struct GNUNET_TIME_Timestamp now)
1235 : {
1236 : struct DenominationKey *dk;
1237 : struct GNUNET_TIME_Timestamp anchor;
1238 :
1239 3141 : anchor = now;
1240 3141 : if (NULL != denom->keys_tail)
1241 : {
1242 : struct GNUNET_TIME_Absolute abs;
1243 :
1244 3068 : abs = GNUNET_TIME_absolute_add (denom->keys_tail->anchor.abs_time,
1245 : GNUNET_TIME_relative_subtract (
1246 : denom->duration_withdraw,
1247 : overlap_duration));
1248 3068 : if (GNUNET_TIME_absolute_cmp (now.abs_time,
1249 : <,
1250 : abs))
1251 3068 : anchor = GNUNET_TIME_absolute_to_timestamp (abs);
1252 : }
1253 3141 : dk = GNUNET_new (struct DenominationKey);
1254 3141 : dk->denom = denom;
1255 3141 : dk->anchor = anchor;
1256 3141 : if (GNUNET_OK !=
1257 3141 : setup_key (dk,
1258 : denom->keys_tail))
1259 : {
1260 0 : GNUNET_break (0);
1261 0 : GNUNET_free (dk);
1262 0 : GNUNET_SCHEDULER_shutdown ();
1263 0 : globals->global_ret = EXIT_FAILURE;
1264 0 : return GNUNET_SYSERR;
1265 : }
1266 3141 : return GNUNET_OK;
1267 : }
1268 :
1269 :
1270 : /**
1271 : * At what time does this denomination require its next action?
1272 : * Basically, the minimum of the withdraw expiration time of the
1273 : * oldest denomination key, and the withdraw expiration time of
1274 : * the newest denomination key minus the #lookahead_sign time.
1275 : *
1276 : * @param denom denomination to compute action time for
1277 : */
1278 : static struct GNUNET_TIME_Absolute
1279 187 : denomination_action_time (const struct Denomination *denom)
1280 : {
1281 187 : struct DenominationKey *head = denom->keys_head;
1282 187 : struct DenominationKey *tail = denom->keys_tail;
1283 : struct GNUNET_TIME_Absolute tt;
1284 :
1285 187 : if (NULL == head)
1286 0 : return GNUNET_TIME_UNIT_ZERO_ABS;
1287 187 : tt = GNUNET_TIME_absolute_subtract (
1288 : GNUNET_TIME_absolute_subtract (
1289 : GNUNET_TIME_absolute_add (tail->anchor.abs_time,
1290 : denom->duration_withdraw),
1291 : lookahead_sign),
1292 : overlap_duration);
1293 187 : if (head->rc > 0)
1294 0 : return tt; /* head expiration does not count due to rc > 0 */
1295 187 : return GNUNET_TIME_absolute_min (
1296 : GNUNET_TIME_absolute_add (head->anchor.abs_time,
1297 : denom->duration_withdraw),
1298 : tt);
1299 : }
1300 :
1301 :
1302 : /**
1303 : * Create new keys and expire ancient keys of the given denomination @a denom.
1304 : * Removes the @a denom from the #denom_head DLL and re-insert its at the
1305 : * correct location sorted by next maintenance activity.
1306 : *
1307 : * @param[in,out] denom denomination to update material for
1308 : * @param now current time to use (to get many keys to use the exact same time)
1309 : * @param[in,out] wake set to true if we should wake the clients
1310 : * @return #GNUNET_OK on success
1311 : */
1312 : static enum GNUNET_GenericReturnValue
1313 96 : update_keys (struct Denomination *denom,
1314 : struct GNUNET_TIME_Timestamp now,
1315 : bool *wake)
1316 : {
1317 : /* create new denomination keys */
1318 96 : if (NULL != denom->keys_tail)
1319 23 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1320 : "Updating keys of denomination `%s', last key %s valid for another %s\n",
1321 : denom->section,
1322 : GNUNET_h2s (&denom->keys_tail->h_rsa.hash),
1323 : GNUNET_TIME_relative2s (
1324 : GNUNET_TIME_absolute_get_remaining (
1325 : GNUNET_TIME_absolute_subtract (
1326 : GNUNET_TIME_absolute_add (
1327 : denom->keys_tail->anchor.abs_time,
1328 : denom->duration_withdraw),
1329 : overlap_duration)),
1330 : GNUNET_YES));
1331 6401 : while ( (NULL == denom->keys_tail) ||
1332 3164 : GNUNET_TIME_absolute_is_past (
1333 : GNUNET_TIME_absolute_subtract (
1334 : GNUNET_TIME_absolute_subtract (
1335 3164 : GNUNET_TIME_absolute_add (denom->keys_tail->anchor.abs_time,
1336 : denom->duration_withdraw),
1337 : lookahead_sign),
1338 : overlap_duration)) )
1339 : {
1340 3141 : if (! *wake)
1341 : {
1342 1 : key_gen++;
1343 1 : *wake = true;
1344 : }
1345 3141 : if (GNUNET_OK !=
1346 3141 : create_key (denom,
1347 : now))
1348 : {
1349 0 : GNUNET_break (0);
1350 0 : globals->global_ret = EXIT_FAILURE;
1351 0 : GNUNET_SCHEDULER_shutdown ();
1352 0 : return GNUNET_SYSERR;
1353 : }
1354 : }
1355 : /* remove expired denomination keys */
1356 194 : while ( (NULL != denom->keys_head) &&
1357 97 : GNUNET_TIME_absolute_is_past
1358 97 : (GNUNET_TIME_absolute_add (denom->keys_head->anchor.abs_time,
1359 : denom->duration_withdraw)) )
1360 : {
1361 1 : struct DenominationKey *key = denom->keys_head;
1362 1 : struct DenominationKey *nxt = key->next;
1363 :
1364 1 : if (0 != key->rc)
1365 0 : break; /* later */
1366 1 : GNUNET_CONTAINER_DLL_remove (denom->keys_head,
1367 : denom->keys_tail,
1368 : key);
1369 1 : GNUNET_assert (GNUNET_OK ==
1370 : GNUNET_CONTAINER_multihashmap_remove (
1371 : keys,
1372 : &key->h_rsa.hash,
1373 : key));
1374 2 : if ( (! key->purge) &&
1375 1 : (0 != unlink (key->filename)) )
1376 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1377 : "unlink",
1378 : key->filename);
1379 1 : GNUNET_free (key->filename);
1380 1 : GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
1381 1 : GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
1382 1 : GNUNET_free (key->an);
1383 1 : GNUNET_free (key);
1384 1 : key = nxt;
1385 : }
1386 :
1387 : /* Update position of 'denom' in #denom_head DLL: sort by action time */
1388 : {
1389 : struct Denomination *before;
1390 : struct GNUNET_TIME_Absolute at;
1391 :
1392 96 : at = denomination_action_time (denom);
1393 96 : GNUNET_CONTAINER_DLL_remove (denom_head,
1394 : denom_tail,
1395 : denom);
1396 96 : before = NULL;
1397 96 : for (struct Denomination *pos = denom_head;
1398 96 : NULL != pos;
1399 0 : pos = pos->next)
1400 : {
1401 76 : if (GNUNET_TIME_absolute_cmp (denomination_action_time (pos),
1402 : >=,
1403 : at))
1404 76 : break;
1405 0 : before = pos;
1406 : }
1407 96 : GNUNET_CONTAINER_DLL_insert_after (denom_head,
1408 : denom_tail,
1409 : before,
1410 : denom);
1411 : }
1412 96 : return GNUNET_OK;
1413 : }
1414 :
1415 :
1416 : /**
1417 : * Task run periodically to expire keys and/or generate fresh ones.
1418 : *
1419 : * @param cls NULL
1420 : */
1421 : static void
1422 15 : update_denominations (void *cls)
1423 : {
1424 : struct Denomination *denom;
1425 : struct GNUNET_TIME_Absolute now;
1426 : struct GNUNET_TIME_Timestamp t;
1427 15 : bool wake = false;
1428 :
1429 : (void) cls;
1430 15 : keygen_task = NULL;
1431 15 : now = GNUNET_TIME_absolute_get ();
1432 15 : t = GNUNET_TIME_absolute_to_timestamp (now);
1433 15 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434 : "Updating denominations ...\n");
1435 15 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1436 : do {
1437 15 : denom = denom_head;
1438 15 : if (GNUNET_OK !=
1439 15 : update_keys (denom,
1440 : t,
1441 : &wake))
1442 0 : return;
1443 15 : } while (denom != denom_head);
1444 15 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1445 15 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1446 : "Updating denominations finished ...\n");
1447 15 : if (wake)
1448 1 : TES_wake_clients ();
1449 15 : keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
1450 : &update_denominations,
1451 : NULL);
1452 : }
1453 :
1454 :
1455 : /**
1456 : * Parse private key of denomination @a denom in @a buf.
1457 : *
1458 : * @param[out] denom denomination of the key
1459 : * @param filename name of the file we are parsing, for logging
1460 : * @param buf key material
1461 : * @param buf_size number of bytes in @a buf
1462 : */
1463 : static void
1464 424 : parse_key (struct Denomination *denom,
1465 : const char *filename,
1466 : const void *buf,
1467 : size_t buf_size)
1468 : {
1469 : struct GNUNET_CRYPTO_RsaPrivateKey *priv;
1470 : char *anchor_s;
1471 : char dummy;
1472 : unsigned long long anchor_ll;
1473 : struct GNUNET_TIME_Timestamp anchor;
1474 :
1475 424 : anchor_s = strrchr (filename,
1476 : '/');
1477 424 : if (NULL == anchor_s)
1478 : {
1479 : /* File in a directory without '/' in the name, this makes no sense. */
1480 0 : GNUNET_break (0);
1481 0 : return;
1482 : }
1483 424 : anchor_s++;
1484 424 : if (1 != sscanf (anchor_s,
1485 : "%llu%c",
1486 : &anchor_ll,
1487 : &dummy))
1488 : {
1489 : /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
1490 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1491 : "Filename `%s' invalid for key file, skipping\n",
1492 : filename);
1493 0 : return;
1494 : }
1495 : anchor.abs_time.abs_value_us
1496 424 : = anchor_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1497 848 : if (anchor_ll != anchor.abs_time.abs_value_us
1498 424 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
1499 : {
1500 : /* Integer overflow. Bad, invalid filename. */
1501 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1502 : "Filename `%s' invalid for key file, skipping\n",
1503 : filename);
1504 0 : return;
1505 : }
1506 424 : priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
1507 : buf_size);
1508 424 : if (NULL == priv)
1509 : {
1510 : /* Parser failure. */
1511 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1512 : "File `%s' is malformed, skipping\n",
1513 : filename);
1514 0 : return;
1515 : }
1516 :
1517 : {
1518 : struct GNUNET_CRYPTO_RsaPublicKey *pub;
1519 : struct DenominationKey *dk;
1520 : struct DenominationKey *before;
1521 :
1522 424 : pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
1523 424 : if (NULL == pub)
1524 : {
1525 0 : GNUNET_break (0);
1526 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
1527 0 : return;
1528 : }
1529 424 : dk = GNUNET_new (struct DenominationKey);
1530 424 : dk->denom_priv = priv;
1531 424 : dk->denom = denom;
1532 424 : dk->anchor = anchor;
1533 424 : dk->filename = GNUNET_strdup (filename);
1534 424 : GNUNET_CRYPTO_rsa_public_key_hash (pub,
1535 : &dk->h_rsa.hash);
1536 424 : dk->denom_pub = pub;
1537 424 : generate_response (dk);
1538 424 : if (GNUNET_OK !=
1539 424 : GNUNET_CONTAINER_multihashmap_put (
1540 : keys,
1541 424 : &dk->h_rsa.hash,
1542 : dk,
1543 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1544 : {
1545 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1546 : "Duplicate private key %s detected in file `%s'. Skipping.\n",
1547 : GNUNET_h2s (&dk->h_rsa.hash),
1548 : filename);
1549 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
1550 0 : GNUNET_CRYPTO_rsa_public_key_free (pub);
1551 0 : GNUNET_free (dk->an);
1552 0 : GNUNET_free (dk);
1553 0 : return;
1554 : }
1555 424 : before = NULL;
1556 424 : for (struct DenominationKey *pos = denom->keys_head;
1557 424 : NULL != pos;
1558 0 : pos = pos->next)
1559 : {
1560 416 : if (GNUNET_TIME_timestamp_cmp (pos->anchor,
1561 : >,
1562 : anchor))
1563 416 : break;
1564 0 : before = pos;
1565 : }
1566 424 : GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
1567 : denom->keys_tail,
1568 : before,
1569 : dk);
1570 424 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1571 : "Imported key %s from `%s'\n",
1572 : GNUNET_h2s (&dk->h_rsa.hash),
1573 : filename);
1574 : }
1575 : }
1576 :
1577 :
1578 : /**
1579 : * Import a private key from @a filename for the denomination
1580 : * given in @a cls.
1581 : *
1582 : * @param[in,out] cls a `struct Denomiantion`
1583 : * @param filename name of a file in the directory
1584 : * @return #GNUNET_OK (always, continue to iterate)
1585 : */
1586 : static enum GNUNET_GenericReturnValue
1587 424 : import_key (void *cls,
1588 : const char *filename)
1589 : {
1590 424 : struct Denomination *denom = cls;
1591 : struct GNUNET_DISK_FileHandle *fh;
1592 : struct GNUNET_DISK_MapHandle *map;
1593 : void *ptr;
1594 : int fd;
1595 : struct stat sbuf;
1596 :
1597 : {
1598 : struct stat lsbuf;
1599 :
1600 424 : if (0 != lstat (filename,
1601 : &lsbuf))
1602 : {
1603 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1604 : "lstat",
1605 : filename);
1606 0 : return GNUNET_OK;
1607 : }
1608 424 : if (! S_ISREG (lsbuf.st_mode))
1609 : {
1610 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1611 : "File `%s' is not a regular file, which is not allowed for private keys!\n",
1612 : filename);
1613 0 : return GNUNET_OK;
1614 : }
1615 : }
1616 :
1617 424 : fd = open (filename,
1618 : O_RDONLY | O_CLOEXEC);
1619 424 : if (-1 == fd)
1620 : {
1621 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1622 : "open",
1623 : filename);
1624 0 : return GNUNET_OK;
1625 : }
1626 424 : if (0 != fstat (fd,
1627 : &sbuf))
1628 : {
1629 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1630 : "stat",
1631 : filename);
1632 0 : GNUNET_break (0 == close (fd));
1633 0 : return GNUNET_OK;
1634 : }
1635 424 : if (! S_ISREG (sbuf.st_mode))
1636 : {
1637 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1638 : "File `%s' is not a regular file, which is not allowed for private keys!\n",
1639 : filename);
1640 0 : GNUNET_break (0 == close (fd));
1641 0 : return GNUNET_OK;
1642 : }
1643 424 : if (0 != (sbuf.st_mode & (S_IWUSR | S_IRWXG | S_IRWXO)))
1644 : {
1645 : /* permission are NOT tight, try to patch them up! */
1646 0 : if (0 !=
1647 0 : fchmod (fd,
1648 : S_IRUSR))
1649 : {
1650 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1651 : "fchmod",
1652 : filename);
1653 : /* refuse to use key if file has wrong permissions */
1654 0 : GNUNET_break (0 == close (fd));
1655 0 : return GNUNET_OK;
1656 : }
1657 : }
1658 424 : fh = GNUNET_DISK_get_handle_from_int_fd (fd);
1659 424 : if (NULL == fh)
1660 : {
1661 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1662 : "open",
1663 : filename);
1664 0 : GNUNET_break (0 == close (fd));
1665 0 : return GNUNET_OK;
1666 : }
1667 424 : if (sbuf.st_size > 16 * 1024)
1668 : {
1669 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1670 : "File `%s' too big to be a private key\n",
1671 : filename);
1672 0 : GNUNET_DISK_file_close (fh);
1673 0 : return GNUNET_OK;
1674 : }
1675 424 : ptr = GNUNET_DISK_file_map (fh,
1676 : &map,
1677 : GNUNET_DISK_MAP_TYPE_READ,
1678 424 : (size_t) sbuf.st_size);
1679 424 : if (NULL == ptr)
1680 : {
1681 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1682 : "mmap",
1683 : filename);
1684 0 : GNUNET_DISK_file_close (fh);
1685 0 : return GNUNET_OK;
1686 : }
1687 424 : parse_key (denom,
1688 : filename,
1689 : ptr,
1690 424 : (size_t) sbuf.st_size);
1691 424 : GNUNET_DISK_file_unmap (map);
1692 424 : GNUNET_DISK_file_close (fh);
1693 424 : return GNUNET_OK;
1694 : }
1695 :
1696 :
1697 : /**
1698 : * Parse configuration for denomination type parameters. Also determines
1699 : * our anchor by looking at the existing denominations of the same type.
1700 : *
1701 : * @param cfg configuration to use
1702 : * @param ct section in the configuration file giving the denomination type parameters
1703 : * @param[out] denom set to the denomination parameters from the configuration
1704 : * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
1705 : */
1706 : static enum GNUNET_GenericReturnValue
1707 81 : parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
1708 : const char *ct,
1709 : struct Denomination *denom)
1710 : {
1711 : unsigned long long rsa_keysize;
1712 : char *secname;
1713 :
1714 81 : GNUNET_asprintf (&secname,
1715 : "%s-secmod-rsa",
1716 81 : globals->section);
1717 81 : if (GNUNET_OK !=
1718 81 : GNUNET_CONFIGURATION_get_value_time (cfg,
1719 : ct,
1720 : "DURATION_WITHDRAW",
1721 : &denom->duration_withdraw))
1722 : {
1723 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1724 : ct,
1725 : "DURATION_WITHDRAW");
1726 0 : GNUNET_free (secname);
1727 0 : return GNUNET_SYSERR;
1728 : }
1729 81 : if (GNUNET_TIME_relative_cmp (overlap_duration,
1730 : >=,
1731 : denom->duration_withdraw))
1732 : {
1733 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1734 : secname,
1735 : "OVERLAP_DURATION",
1736 : "Value given must be smaller than value for DURATION_WITHDRAW!");
1737 0 : GNUNET_free (secname);
1738 0 : return GNUNET_SYSERR;
1739 : }
1740 81 : if (GNUNET_OK !=
1741 81 : GNUNET_CONFIGURATION_get_value_number (cfg,
1742 : ct,
1743 : "RSA_KEYSIZE",
1744 : &rsa_keysize))
1745 : {
1746 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1747 : ct,
1748 : "RSA_KEYSIZE");
1749 0 : GNUNET_free (secname);
1750 0 : return GNUNET_SYSERR;
1751 : }
1752 81 : if ( (rsa_keysize > 4 * 2048) ||
1753 81 : (rsa_keysize < 1024) )
1754 : {
1755 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1756 : ct,
1757 : "RSA_KEYSIZE",
1758 : "Given RSA keysize outside of permitted range [1024,8192]\n");
1759 0 : GNUNET_free (secname);
1760 0 : return GNUNET_SYSERR;
1761 : }
1762 81 : GNUNET_free (secname);
1763 81 : denom->rsa_keysize = (unsigned int) rsa_keysize;
1764 81 : denom->section = GNUNET_strdup (ct);
1765 81 : return GNUNET_OK;
1766 : }
1767 :
1768 :
1769 : /**
1770 : * Closure for #load_denominations.
1771 : */
1772 : struct LoadContext
1773 : {
1774 :
1775 : /**
1776 : * Configuration to use.
1777 : */
1778 : const struct GNUNET_CONFIGURATION_Handle *cfg;
1779 :
1780 : /**
1781 : * Current time to use.
1782 : */
1783 : struct GNUNET_TIME_Timestamp t;
1784 :
1785 : /**
1786 : * Status, to be set to #GNUNET_SYSERR on failure
1787 : */
1788 : enum GNUNET_GenericReturnValue ret;
1789 : };
1790 :
1791 :
1792 : /**
1793 : * Generate new denomination signing keys for the denomination type of the given @a
1794 : * denomination_alias.
1795 : *
1796 : * @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure
1797 : * @param denomination_alias name of the denomination's section in the configuration
1798 : */
1799 : static void
1800 953 : load_denominations (void *cls,
1801 : const char *denomination_alias)
1802 : {
1803 953 : struct LoadContext *ctx = cls;
1804 : struct Denomination *denom;
1805 953 : bool wake = true;
1806 : char *cipher;
1807 :
1808 953 : if ( (0 != strncasecmp (denomination_alias,
1809 : "coin_",
1810 820 : strlen ("coin_"))) &&
1811 820 : (0 != strncasecmp (denomination_alias,
1812 : "coin-",
1813 : strlen ("coin-"))) )
1814 872 : return; /* not a denomination type definition */
1815 133 : if (GNUNET_OK !=
1816 133 : GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
1817 : denomination_alias,
1818 : "CIPHER",
1819 : &cipher))
1820 : {
1821 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1822 : denomination_alias,
1823 : "CIPHER");
1824 0 : return;
1825 : }
1826 133 : if (0 != strcmp (cipher, "RSA"))
1827 : {
1828 52 : GNUNET_free (cipher);
1829 52 : return; /* Ignore denominations of other types than CS */
1830 : }
1831 81 : GNUNET_free (cipher);
1832 81 : denom = GNUNET_new (struct Denomination);
1833 81 : if (GNUNET_OK !=
1834 81 : parse_denomination_cfg (ctx->cfg,
1835 : denomination_alias,
1836 : denom))
1837 : {
1838 0 : ctx->ret = GNUNET_SYSERR;
1839 0 : GNUNET_free (denom);
1840 0 : return;
1841 : }
1842 81 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1843 : "Loading keys for denomination %s\n",
1844 : denom->section);
1845 : {
1846 : char *dname;
1847 :
1848 81 : GNUNET_asprintf (&dname,
1849 : "%s/%s",
1850 : keydir,
1851 : denom->section);
1852 81 : GNUNET_break (GNUNET_OK ==
1853 : GNUNET_DISK_directory_create (dname));
1854 81 : GNUNET_DISK_directory_scan (dname,
1855 : &import_key,
1856 : denom);
1857 81 : GNUNET_free (dname);
1858 : }
1859 81 : GNUNET_CONTAINER_DLL_insert (denom_head,
1860 : denom_tail,
1861 : denom);
1862 81 : update_keys (denom,
1863 : ctx->t,
1864 : &wake);
1865 : }
1866 :
1867 :
1868 : /**
1869 : * Load the various duration values from @a cfg
1870 : *
1871 : * @param cfg configuration to use
1872 : * @return #GNUNET_OK on success
1873 : */
1874 : static enum GNUNET_GenericReturnValue
1875 20 : load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
1876 : {
1877 : char *secname;
1878 :
1879 20 : GNUNET_asprintf (&secname,
1880 : "%s-secmod-rsa",
1881 20 : globals->section);
1882 20 : if (GNUNET_OK !=
1883 20 : GNUNET_CONFIGURATION_get_value_time (cfg,
1884 : secname,
1885 : "OVERLAP_DURATION",
1886 : &overlap_duration))
1887 : {
1888 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1889 : secname,
1890 : "OVERLAP_DURATION");
1891 0 : GNUNET_free (secname);
1892 0 : return GNUNET_SYSERR;
1893 : }
1894 20 : if (GNUNET_OK !=
1895 20 : GNUNET_CONFIGURATION_get_value_time (cfg,
1896 : secname,
1897 : "LOOKAHEAD_SIGN",
1898 : &lookahead_sign))
1899 : {
1900 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1901 : secname,
1902 : "LOOKAHEAD_SIGN");
1903 0 : GNUNET_free (secname);
1904 0 : return GNUNET_SYSERR;
1905 : }
1906 20 : GNUNET_free (secname);
1907 20 : return GNUNET_OK;
1908 : }
1909 :
1910 :
1911 : /**
1912 : * Function run on shutdown. Stops the various jobs (nicely).
1913 : *
1914 : * @param cls NULL
1915 : */
1916 : static void
1917 20 : do_shutdown (void *cls)
1918 : {
1919 : (void) cls;
1920 20 : TES_listen_stop ();
1921 20 : if (NULL != keygen_task)
1922 : {
1923 13 : GNUNET_SCHEDULER_cancel (keygen_task);
1924 13 : keygen_task = NULL;
1925 : }
1926 20 : stop_workers ();
1927 20 : sem_done (&worker_sem);
1928 20 : }
1929 :
1930 :
1931 : void
1932 20 : TALER_SECMOD_rsa_run (void *cls,
1933 : char *const *args,
1934 : const char *cfgfile,
1935 : const struct GNUNET_CONFIGURATION_Handle *cfg)
1936 : {
1937 : static struct TES_Callbacks cb = {
1938 : .dispatch = rsa_work_dispatch,
1939 : .updater = rsa_update_client_keys,
1940 : .init = rsa_client_init
1941 : };
1942 20 : struct TALER_SECMOD_Options *opt = cls;
1943 : char *secname;
1944 :
1945 : (void) args;
1946 : (void) cfgfile;
1947 20 : globals = opt;
1948 20 : if (GNUNET_TIME_timestamp_cmp (opt->global_now,
1949 : !=,
1950 : opt->global_now_tmp))
1951 : {
1952 : /* The user gave "--now", use it! */
1953 0 : opt->global_now = opt->global_now_tmp;
1954 : }
1955 : else
1956 : {
1957 : /* get current time again, we may be timetraveling! */
1958 20 : opt->global_now = GNUNET_TIME_timestamp_get ();
1959 : }
1960 20 : GNUNET_asprintf (&secname,
1961 : "%s-secmod-rsa",
1962 : opt->section);
1963 20 : if (GNUNET_OK !=
1964 20 : GNUNET_CONFIGURATION_get_value_filename (cfg,
1965 : secname,
1966 : "KEY_DIR",
1967 : &keydir))
1968 : {
1969 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1970 : secname,
1971 : "KEY_DIR");
1972 0 : GNUNET_free (secname);
1973 0 : opt->global_ret = EXIT_NOTCONFIGURED;
1974 7 : return;
1975 : }
1976 20 : if (GNUNET_OK !=
1977 20 : load_durations (cfg))
1978 : {
1979 0 : opt->global_ret = EXIT_NOTCONFIGURED;
1980 0 : GNUNET_free (secname);
1981 0 : return;
1982 : }
1983 20 : opt->global_ret = TES_listen_start (cfg,
1984 : secname,
1985 : &cb);
1986 20 : GNUNET_free (secname);
1987 20 : if (0 != opt->global_ret)
1988 0 : return;
1989 20 : sem_init (&worker_sem,
1990 : 0);
1991 20 : GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1992 : NULL);
1993 20 : if (0 == opt->max_workers)
1994 : {
1995 : long lret;
1996 :
1997 0 : lret = sysconf (_SC_NPROCESSORS_CONF);
1998 0 : if (lret <= 0)
1999 0 : lret = 1;
2000 0 : opt->max_workers = (unsigned int) lret;
2001 : }
2002 :
2003 340 : for (unsigned int i = 0; i<opt->max_workers; i++)
2004 320 : if (GNUNET_OK !=
2005 320 : start_worker ())
2006 : {
2007 0 : GNUNET_SCHEDULER_shutdown ();
2008 0 : return;
2009 : }
2010 : /* Load denominations */
2011 20 : keys = GNUNET_CONTAINER_multihashmap_create (65536,
2012 : true);
2013 : {
2014 20 : struct LoadContext lc = {
2015 : .cfg = cfg,
2016 : .ret = GNUNET_OK,
2017 : .t = opt->global_now
2018 : };
2019 :
2020 20 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
2021 20 : GNUNET_CONFIGURATION_iterate_sections (cfg,
2022 : &load_denominations,
2023 : &lc);
2024 20 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
2025 20 : if (GNUNET_OK != lc.ret)
2026 : {
2027 0 : opt->global_ret = EXIT_FAILURE;
2028 0 : GNUNET_SCHEDULER_shutdown ();
2029 0 : return;
2030 : }
2031 : }
2032 20 : if (NULL == denom_head)
2033 : {
2034 7 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2035 : "No RSA denominations configured\n");
2036 7 : TES_wake_clients ();
2037 7 : return;
2038 : }
2039 : /* start job to keep keys up-to-date; MUST be run before the #listen_task,
2040 : hence with priority. */
2041 13 : keygen_task = GNUNET_SCHEDULER_add_with_priority (
2042 : GNUNET_SCHEDULER_PRIORITY_URGENT,
2043 : &update_denominations,
2044 : NULL);
2045 : }
|