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