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