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