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