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 257 : generate_response (struct DenominationKey *dk)
364 : {
365 257 : struct Denomination *denom = dk->denom;
366 257 : 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 257 : buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub,
375 : &buf);
376 257 : GNUNET_assert (buf_len < UINT16_MAX);
377 257 : GNUNET_assert (nlen < UINT16_MAX);
378 257 : tlen = buf_len + nlen + sizeof (*an);
379 257 : GNUNET_assert (tlen < UINT16_MAX);
380 257 : an = GNUNET_malloc (tlen);
381 257 : an->header.size = htons ((uint16_t) tlen);
382 257 : an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
383 257 : an->pub_size = htons ((uint16_t) buf_len);
384 257 : an->section_name_len = htons ((uint16_t) nlen);
385 257 : 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 257 : effective_duration = GNUNET_TIME_absolute_get_difference (
390 : dk->anchor_start.abs_time,
391 : dk->anchor_end.abs_time);
392 257 : an->duration_withdraw = GNUNET_TIME_relative_hton (effective_duration);
393 :
394 257 : TALER_exchange_secmod_rsa_sign (&dk->h_rsa,
395 257 : denom->section,
396 : dk->anchor_start,
397 : effective_duration,
398 : &TES_smpriv,
399 : &an->secm_sig);
400 257 : an->secm_pub = TES_smpub;
401 257 : p = (void *) &an[1];
402 257 : GNUNET_memcpy (p,
403 : buf,
404 : buf_len);
405 257 : GNUNET_free (buf);
406 257 : GNUNET_memcpy (p + buf_len,
407 : denom->section,
408 : nlen);
409 257 : dk->an = an;
410 257 : }
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 1446 : 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 1446 : struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
429 :
430 1434 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
431 1464 : dk = GNUNET_CONTAINER_multihashmap_get (keys,
432 : &h_rsa->hash);
433 1464 : 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 1461 : if (dk->purge)
442 : {
443 : /* key was revoked, it must not be used for signing anymore */
444 8 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
445 8 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
446 : "Signing request failed, denomination key %s was revoked\n",
447 : GNUNET_h2s (&h_rsa->hash));
448 8 : return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED;
449 : }
450 1453 : 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 268 : 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 267 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY;
459 : }
460 1185 : 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 1185 : 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 1185 : GNUNET_assert (dk->rc < UINT_MAX);
478 1185 : dk->rc++;
479 1185 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
480 : rsa_signature
481 1185 : = GNUNET_CRYPTO_rsa_sign_blinded (dk->denom_priv,
482 : bm);
483 1183 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
484 1185 : GNUNET_assert (dk->rc > 0);
485 1185 : dk->rc--;
486 1185 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
487 1185 : 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 1185 : 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 1182 : *rsa_signaturep = rsa_signature;
500 1182 : 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 279 : fail_sign (struct TES_Client *client,
513 : enum TALER_ErrorCode ec)
514 : {
515 279 : struct TALER_CRYPTO_SignFailure sf = {
516 279 : .header.size = htons (sizeof (sf)),
517 279 : .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
518 279 : .ec = htonl (ec)
519 : };
520 :
521 279 : 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 1183 : 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 1183 : buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature,
544 : &buf);
545 1185 : GNUNET_CRYPTO_rsa_signature_free (rsa_signature);
546 1185 : tsize = sizeof (*sr) + buf_size;
547 1185 : GNUNET_assert (tsize < UINT16_MAX);
548 1185 : sr = GNUNET_malloc (tsize);
549 1185 : sr->header.size = htons (tsize);
550 1185 : sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
551 1185 : GNUNET_memcpy (&sr[1],
552 : buf,
553 : buf_size);
554 1185 : GNUNET_free (buf);
555 1184 : ret = TES_transmit (client->csock,
556 1184 : &sr->header);
557 1184 : GNUNET_free (sr);
558 1184 : 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 1811 : sem_init (struct Semaphore *sem,
603 : unsigned int val)
604 : {
605 1811 : GNUNET_assert (0 ==
606 : pthread_mutex_init (&sem->mutex,
607 : NULL));
608 1811 : GNUNET_assert (0 ==
609 : pthread_cond_init (&sem->cv,
610 : NULL));
611 1811 : sem->ctr = val;
612 1811 : }
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 5032 : sem_down (struct Semaphore *sem)
622 : {
623 5032 : GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
624 7877 : while (0 == sem->ctr)
625 : {
626 2859 : pthread_cond_wait (&sem->cv,
627 : &sem->mutex);
628 : }
629 5018 : sem->ctr--;
630 5018 : GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
631 5015 : }
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 5004 : sem_up (struct Semaphore *sem)
641 : {
642 5004 : GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
643 5009 : sem->ctr++;
644 5009 : pthread_cond_signal (&sem->cv);
645 4993 : GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
646 5010 : }
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 1810 : sem_done (struct Semaphore *sem)
656 : {
657 1810 : GNUNET_break (0 == pthread_cond_destroy (&sem->cv));
658 1812 : GNUNET_break (0 == pthread_mutex_destroy (&sem->mutex));
659 1811 : }
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 324 : worker (void *cls)
671 : {
672 324 : struct Worker *w = cls;
673 :
674 : while (true)
675 : {
676 1780 : GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
677 1788 : GNUNET_CONTAINER_DLL_insert (worker_head,
678 : worker_tail,
679 : w);
680 1788 : GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
681 1787 : sem_up (&worker_sem);
682 1786 : sem_down (&w->sem);
683 1776 : if (w->do_shutdown)
684 324 : break;
685 : {
686 1452 : struct BatchJob *bj = w->job;
687 1452 : const struct TALER_CRYPTO_SignRequest *sr = bj->sr;
688 1452 : struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
689 1452 : .blinded_msg = (void *) &sr[1],
690 1452 : .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
691 : };
692 :
693 1452 : bj->ec = do_sign (&sr->h_rsa,
694 : &bm,
695 : &bj->rsa_signature);
696 1458 : sem_up (&bj->sem);
697 1456 : w->job = NULL;
698 : }
699 : }
700 324 : 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 1464 : start_job (const struct TALER_CRYPTO_SignRequest *sr,
712 : struct BatchJob *bj)
713 : {
714 1464 : sem_init (&bj->sem,
715 : 0);
716 1463 : bj->sr = sr;
717 1463 : sem_down (&worker_sem);
718 1464 : GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
719 1464 : bj->worker = worker_head;
720 1464 : GNUNET_CONTAINER_DLL_remove (worker_head,
721 : worker_tail,
722 : bj->worker);
723 1464 : GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
724 1464 : bj->worker->job = bj;
725 1464 : sem_up (&bj->worker->sem);
726 1464 : }
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 : * @return #GNUNET_OK on success, #GNUNET_SYSERR if we
735 : * failed to transmit the reply to @a client
736 : */
737 : static enum GNUNET_GenericReturnValue
738 1464 : finish_job (struct TES_Client *client,
739 : struct BatchJob *bj)
740 : {
741 : enum GNUNET_GenericReturnValue ret;
742 :
743 1464 : sem_down (&bj->sem);
744 1464 : sem_done (&bj->sem);
745 1463 : if (TALER_EC_NONE != bj->ec)
746 279 : return fail_sign (client,
747 : bj->ec);
748 1184 : GNUNET_assert (NULL != bj->rsa_signature);
749 1184 : ret = send_signature (client,
750 : bj->rsa_signature);
751 1184 : bj->rsa_signature = NULL; /* freed in send_signature */
752 1184 : return ret;
753 : }
754 :
755 :
756 : /**
757 : * Handle @a client request @a sr to create a batch of signature. Creates the
758 : * signatures using the respective key and return the results to the client.
759 : *
760 : * @param client the client making the request
761 : * @param bsr the request details
762 : * @return #GNUNET_OK on success
763 : */
764 : static enum GNUNET_GenericReturnValue
765 1009 : handle_batch_sign_request (struct TES_Client *client,
766 : const struct TALER_CRYPTO_BatchSignRequest *bsr)
767 : {
768 1009 : uint32_t bs = ntohl (bsr->batch_size);
769 1009 : uint16_t size = ntohs (bsr->header.size) - sizeof (*bsr);
770 1009 : const void *off = (const void *) &bsr[1];
771 1009 : unsigned int idx = 0;
772 1009 : bool failure = false;
773 1009 : enum GNUNET_GenericReturnValue tret = GNUNET_OK;
774 :
775 : /* an empty batch would be answered with no message at all,
776 : leaving the client waiting for a reply forever */
777 1009 : if ( (0 == bs) ||
778 : (bs > TALER_MAX_COINS) )
779 : {
780 0 : GNUNET_break_op (0);
781 0 : return GNUNET_SYSERR;
782 : }
783 1009 : {
784 1009 : struct BatchJob jobs[bs];
785 :
786 2473 : while ( (idx < bs) &&
787 : (size > sizeof (struct TALER_CRYPTO_SignRequest)) )
788 : {
789 1463 : const struct TALER_CRYPTO_SignRequest *sr = off;
790 1463 : uint16_t s = ntohs (sr->header.size);
791 :
792 1463 : if ( (s > size) ||
793 : (s < sizeof (*sr)) )
794 : {
795 0 : failure = true;
796 0 : bs = idx;
797 0 : break;
798 : }
799 1463 : start_job (sr,
800 1463 : &jobs[idx++]);
801 1464 : off += s;
802 1464 : size -= s;
803 : }
804 1010 : GNUNET_break_op (0 == size);
805 1010 : bs = GNUNET_MIN (bs,
806 : idx);
807 : /* Note: we must finish (and thus reap) *every* job we started,
808 : even once transmission failed, or we would leak workers and
809 : the signatures they produced. */
810 2474 : for (unsigned int i = 0; i<bs; i++)
811 1464 : if (GNUNET_OK !=
812 1464 : finish_job (client,
813 : &jobs[i]))
814 0 : tret = GNUNET_SYSERR;
815 : }
816 1010 : if (GNUNET_OK != tret)
817 0 : return tret; /* client is gone, do not bother with more replies */
818 1010 : if (failure)
819 : {
820 0 : struct TALER_CRYPTO_SignFailure sf = {
821 0 : .header.size = htons (sizeof (sf)),
822 0 : .header.type = htons (TALER_HELPER_RSA_MT_RES_BATCH_FAILURE),
823 0 : .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
824 : };
825 :
826 0 : GNUNET_break (0);
827 0 : return TES_transmit (client->csock,
828 : &sf.header);
829 : }
830 1010 : return GNUNET_OK;
831 : }
832 :
833 :
834 : /**
835 : * Start worker thread for batch processing.
836 : *
837 : * @return #GNUNET_OK on success
838 : */
839 : static enum GNUNET_GenericReturnValue
840 324 : start_worker (void)
841 : {
842 : struct Worker *w;
843 :
844 324 : w = GNUNET_new (struct Worker);
845 324 : sem_init (&w->sem,
846 : 0);
847 324 : if (0 != pthread_create (&w->pt,
848 : NULL,
849 : &worker,
850 : w))
851 : {
852 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
853 : "pthread_create");
854 0 : GNUNET_free (w);
855 0 : return GNUNET_SYSERR;
856 : }
857 324 : workers++;
858 324 : return GNUNET_OK;
859 : }
860 :
861 :
862 : /**
863 : * Stop all worker threads.
864 : */
865 : static void
866 24 : stop_workers (void)
867 : {
868 348 : while (workers > 0)
869 : {
870 : struct Worker *w;
871 : void *result;
872 :
873 324 : sem_down (&worker_sem);
874 324 : GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
875 324 : w = worker_head;
876 324 : GNUNET_CONTAINER_DLL_remove (worker_head,
877 : worker_tail,
878 : w);
879 324 : GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
880 324 : w->do_shutdown = true;
881 324 : sem_up (&w->sem);
882 324 : pthread_join (w->pt,
883 : &result);
884 324 : GNUNET_assert (result == w);
885 324 : sem_done (&w->sem);
886 324 : GNUNET_free (w);
887 324 : workers--;
888 : }
889 24 : }
890 :
891 :
892 : /**
893 : * Initialize key material for denomination key @a dk (also on disk).
894 : *
895 : * @param[in,out] dk denomination key to compute key material for
896 : * @param position where in the DLL will the @a dk go
897 : * @return #GNUNET_OK on success
898 : */
899 : static enum GNUNET_GenericReturnValue
900 248 : setup_key (struct DenominationKey *dk,
901 : struct DenominationKey *position)
902 : {
903 248 : struct Denomination *denom = dk->denom;
904 : struct GNUNET_CRYPTO_RsaPrivateKey *priv;
905 : struct GNUNET_CRYPTO_RsaPublicKey *pub;
906 : size_t buf_size;
907 : void *buf;
908 :
909 248 : priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize);
910 248 : if (NULL == priv)
911 : {
912 0 : GNUNET_break (0);
913 0 : GNUNET_SCHEDULER_shutdown ();
914 0 : globals->global_ret = EXIT_FAILURE;
915 0 : return GNUNET_SYSERR;
916 : }
917 248 : pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
918 248 : if (NULL == pub)
919 : {
920 0 : GNUNET_break (0);
921 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
922 0 : return GNUNET_SYSERR;
923 : }
924 248 : buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
925 : &buf);
926 248 : GNUNET_CRYPTO_rsa_public_key_hash (pub,
927 : &dk->h_rsa.hash);
928 248 : GNUNET_asprintf (
929 : &dk->filename,
930 : "%s/%s/%llu-%llu",
931 : keydir,
932 : denom->section,
933 248 : (unsigned long long) (dk->anchor_start.abs_time.abs_value_us
934 248 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us),
935 248 : (unsigned long long) (dk->anchor_end.abs_time.abs_value_us
936 248 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
937 248 : if (GNUNET_OK !=
938 248 : GNUNET_DISK_fn_write (dk->filename,
939 : buf,
940 : buf_size,
941 : GNUNET_DISK_PERM_USER_READ))
942 : {
943 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
944 : "write",
945 : dk->filename);
946 0 : GNUNET_free (dk->filename);
947 0 : GNUNET_free (buf);
948 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
949 0 : GNUNET_CRYPTO_rsa_public_key_free (pub);
950 0 : return GNUNET_SYSERR;
951 : }
952 248 : GNUNET_free (buf);
953 248 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
954 : "Setup fresh private key %s at %s in `%s' (generation #%llu)\n",
955 : GNUNET_h2s (&dk->h_rsa.hash),
956 : GNUNET_TIME_timestamp2s (dk->anchor_start),
957 : dk->filename,
958 : (unsigned long long) key_gen);
959 248 : dk->denom_priv = priv;
960 248 : dk->denom_pub = pub;
961 248 : dk->key_gen = key_gen;
962 248 : generate_response (dk);
963 248 : if (GNUNET_OK !=
964 248 : GNUNET_CONTAINER_multihashmap_put (
965 : keys,
966 248 : &dk->h_rsa.hash,
967 : dk,
968 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
969 : {
970 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
971 : "Duplicate private key created! Terminating.\n");
972 0 : GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
973 0 : GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
974 0 : GNUNET_free (dk->filename);
975 0 : GNUNET_free (dk->an);
976 0 : GNUNET_free (dk);
977 0 : return GNUNET_SYSERR;
978 : }
979 248 : GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
980 : denom->keys_tail,
981 : position,
982 : dk);
983 248 : return GNUNET_OK;
984 : }
985 :
986 :
987 : /**
988 : * The withdraw period of a key @a dk has expired. Purge it.
989 : *
990 : * @param[in] dk expired denomination key to purge
991 : */
992 : static void
993 12 : purge_key (struct DenominationKey *dk)
994 : {
995 12 : if (dk->purge)
996 0 : return;
997 12 : if (0 != unlink (dk->filename))
998 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
999 : "unlink",
1000 : dk->filename);
1001 12 : GNUNET_free (dk->filename);
1002 12 : dk->purge = true;
1003 12 : dk->key_gen = key_gen;
1004 : }
1005 :
1006 :
1007 : /**
1008 : * A @a client informs us that a key has been revoked.
1009 : * Check if the key is still in use, and if so replace (!)
1010 : * it with a fresh key.
1011 : *
1012 : * @param client the client making the request
1013 : * @param rr the revocation request
1014 : */
1015 : static enum GNUNET_GenericReturnValue
1016 13 : handle_revoke_request (struct TES_Client *client,
1017 : const struct TALER_CRYPTO_RevokeRequest *rr)
1018 : {
1019 : struct DenominationKey *dk;
1020 : struct DenominationKey *ndk;
1021 : struct Denomination *denom;
1022 :
1023 : (void) client;
1024 13 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1025 13 : dk = GNUNET_CONTAINER_multihashmap_get (keys,
1026 : &rr->h_rsa.hash);
1027 13 : if (NULL == dk)
1028 : {
1029 0 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1030 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1031 : "Revocation request ignored, denomination key %s unknown\n",
1032 : GNUNET_h2s (&rr->h_rsa.hash));
1033 0 : return GNUNET_OK;
1034 : }
1035 13 : if (dk->purge)
1036 : {
1037 1 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1038 1 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1039 : "Revocation request ignored, denomination key %s already revoked\n",
1040 : GNUNET_h2s (&rr->h_rsa.hash));
1041 1 : return GNUNET_OK;
1042 : }
1043 :
1044 12 : key_gen++;
1045 12 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1046 : "Revoking key %s, bumping generation to %llu\n",
1047 : GNUNET_h2s (&rr->h_rsa.hash),
1048 : (unsigned long long) key_gen);
1049 12 : purge_key (dk);
1050 :
1051 : /* Setup replacement key */
1052 12 : denom = dk->denom;
1053 12 : ndk = GNUNET_new (struct DenominationKey);
1054 12 : ndk->denom = denom;
1055 12 : ndk->anchor_start = dk->anchor_start;
1056 12 : ndk->anchor_end = dk->anchor_end;
1057 12 : if (GNUNET_OK !=
1058 12 : setup_key (ndk,
1059 : dk))
1060 : {
1061 0 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1062 0 : GNUNET_break (0);
1063 0 : GNUNET_SCHEDULER_shutdown ();
1064 0 : globals->global_ret = EXIT_FAILURE;
1065 0 : return GNUNET_SYSERR;
1066 : }
1067 12 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1068 12 : TES_wake_clients ();
1069 12 : return GNUNET_OK;
1070 : }
1071 :
1072 :
1073 : /**
1074 : * Handle @a hdr message received from @a client.
1075 : *
1076 : * @param client the client that received the message
1077 : * @param hdr message that was received
1078 : * @return #GNUNET_OK on success
1079 : */
1080 : static enum GNUNET_GenericReturnValue
1081 1023 : rsa_work_dispatch (struct TES_Client *client,
1082 : const struct GNUNET_MessageHeader *hdr)
1083 : {
1084 1023 : uint16_t msize = ntohs (hdr->size);
1085 :
1086 1023 : switch (ntohs (hdr->type))
1087 : {
1088 0 : case TALER_HELPER_RSA_MT_REQ_SIGN:
1089 0 : if (msize <= sizeof (struct TALER_CRYPTO_SignRequest))
1090 : {
1091 0 : GNUNET_break_op (0);
1092 0 : return GNUNET_SYSERR;
1093 : }
1094 0 : return handle_sign_request (
1095 : client,
1096 : (const struct TALER_CRYPTO_SignRequest *) hdr);
1097 13 : case TALER_HELPER_RSA_MT_REQ_REVOKE:
1098 13 : if (msize != sizeof (struct TALER_CRYPTO_RevokeRequest))
1099 : {
1100 0 : GNUNET_break_op (0);
1101 0 : return GNUNET_SYSERR;
1102 : }
1103 13 : return handle_revoke_request (
1104 : client,
1105 : (const struct TALER_CRYPTO_RevokeRequest *) hdr);
1106 1009 : case TALER_HELPER_RSA_MT_REQ_BATCH_SIGN:
1107 1009 : if (msize <= sizeof (struct TALER_CRYPTO_BatchSignRequest))
1108 : {
1109 0 : GNUNET_break_op (0);
1110 0 : return GNUNET_SYSERR;
1111 : }
1112 1009 : return handle_batch_sign_request (
1113 : client,
1114 : (const struct TALER_CRYPTO_BatchSignRequest *) hdr);
1115 1 : default:
1116 1 : GNUNET_break_op (0);
1117 0 : return GNUNET_SYSERR;
1118 : }
1119 : }
1120 :
1121 :
1122 : /**
1123 : * Send our initial key set to @a client together with the
1124 : * "sync" terminator.
1125 : *
1126 : * @param client the client to inform
1127 : * @return #GNUNET_OK on success
1128 : */
1129 : static enum GNUNET_GenericReturnValue
1130 32 : rsa_client_init (struct TES_Client *client)
1131 : {
1132 32 : size_t obs = 0;
1133 : char *buf;
1134 :
1135 32 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1136 : "Initializing new client %p\n",
1137 : client);
1138 32 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1139 32 : for (struct Denomination *denom = denom_head;
1140 119 : NULL != denom;
1141 87 : denom = denom->next)
1142 : {
1143 87 : for (struct DenominationKey *dk = denom->keys_head;
1144 392 : NULL != dk;
1145 305 : dk = dk->next)
1146 : {
1147 305 : GNUNET_assert (obs + ntohs (dk->an->header.size)
1148 : > obs);
1149 305 : obs += ntohs (dk->an->header.size);
1150 : }
1151 : }
1152 32 : buf = GNUNET_malloc (obs);
1153 32 : obs = 0;
1154 32 : for (struct Denomination *denom = denom_head;
1155 119 : NULL != denom;
1156 87 : denom = denom->next)
1157 : {
1158 87 : for (struct DenominationKey *dk = denom->keys_head;
1159 392 : NULL != dk;
1160 305 : dk = dk->next)
1161 : {
1162 305 : GNUNET_memcpy (&buf[obs],
1163 : dk->an,
1164 : ntohs (dk->an->header.size));
1165 305 : GNUNET_assert (obs + ntohs (dk->an->header.size)
1166 : > obs);
1167 305 : obs += ntohs (dk->an->header.size);
1168 : }
1169 : }
1170 32 : client->key_gen = key_gen;
1171 32 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1172 32 : if (GNUNET_OK !=
1173 32 : TES_transmit_raw (client->csock,
1174 : obs,
1175 : buf))
1176 : {
1177 0 : GNUNET_free (buf);
1178 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1179 : "Client %p must have disconnected\n",
1180 : client);
1181 0 : return GNUNET_SYSERR;
1182 : }
1183 32 : GNUNET_free (buf);
1184 : {
1185 32 : struct GNUNET_MessageHeader synced = {
1186 32 : .type = htons (TALER_HELPER_RSA_SYNCED),
1187 32 : .size = htons (sizeof (synced))
1188 : };
1189 :
1190 32 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1191 : "Sending RSA SYNCED message to %p\n",
1192 : client);
1193 32 : if (GNUNET_OK !=
1194 32 : TES_transmit (client->csock,
1195 : &synced))
1196 : {
1197 0 : GNUNET_break (0);
1198 0 : return GNUNET_SYSERR;
1199 : }
1200 : }
1201 32 : return GNUNET_OK;
1202 : }
1203 :
1204 :
1205 : /**
1206 : * Notify @a client about all changes to the keys since
1207 : * the last generation known to the @a client.
1208 : *
1209 : * @param client the client to notify
1210 : * @return #GNUNET_OK on success
1211 : */
1212 : static enum GNUNET_GenericReturnValue
1213 32 : rsa_update_client_keys (struct TES_Client *client)
1214 : {
1215 32 : size_t obs = 0;
1216 : char *buf;
1217 : enum GNUNET_GenericReturnValue ret;
1218 :
1219 32 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1220 32 : for (struct Denomination *denom = denom_head;
1221 202 : NULL != denom;
1222 170 : denom = denom->next)
1223 : {
1224 170 : for (struct DenominationKey *key = denom->keys_head;
1225 728 : NULL != key;
1226 558 : key = key->next)
1227 : {
1228 558 : if (key->key_gen <= client->key_gen)
1229 530 : continue;
1230 28 : if (key->purge)
1231 12 : obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
1232 : else
1233 16 : obs += ntohs (key->an->header.size);
1234 : }
1235 : }
1236 32 : if (0 == obs)
1237 : {
1238 : /* nothing to do */
1239 16 : client->key_gen = key_gen;
1240 16 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1241 16 : return GNUNET_OK;
1242 : }
1243 16 : buf = GNUNET_malloc (obs);
1244 16 : obs = 0;
1245 16 : for (struct Denomination *denom = denom_head;
1246 113 : NULL != denom;
1247 97 : denom = denom->next)
1248 : {
1249 97 : for (struct DenominationKey *key = denom->keys_head;
1250 425 : NULL != key;
1251 328 : key = key->next)
1252 : {
1253 328 : if (key->key_gen <= client->key_gen)
1254 300 : continue;
1255 28 : if (key->purge)
1256 : {
1257 12 : struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
1258 12 : .header.type = htons (TALER_HELPER_RSA_MT_PURGE),
1259 12 : .header.size = htons (sizeof (pn)),
1260 : .h_rsa = key->h_rsa
1261 : };
1262 :
1263 12 : GNUNET_memcpy (&buf[obs],
1264 : &pn,
1265 : sizeof (pn));
1266 12 : GNUNET_assert (obs + sizeof (pn)
1267 : > obs);
1268 12 : obs += sizeof (pn);
1269 : }
1270 : else
1271 : {
1272 16 : GNUNET_memcpy (&buf[obs],
1273 : key->an,
1274 : ntohs (key->an->header.size));
1275 16 : GNUNET_assert (obs + ntohs (key->an->header.size)
1276 : > obs);
1277 16 : obs += ntohs (key->an->header.size);
1278 : }
1279 : }
1280 : }
1281 16 : client->key_gen = key_gen;
1282 16 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1283 16 : ret = TES_transmit_raw (client->csock,
1284 : obs,
1285 : buf);
1286 16 : GNUNET_free (buf);
1287 16 : return ret;
1288 : }
1289 :
1290 :
1291 : /**
1292 : * Create a new denomination key (we do not have enough).
1293 : *
1294 : * @param[in,out] denom denomination key to create
1295 : * @param anchor_start when to start key signing validity
1296 : * @param anchor_end when to end key signing validity
1297 : * @return #GNUNET_OK on success
1298 : */
1299 : static enum GNUNET_GenericReturnValue
1300 236 : create_key (struct Denomination *denom,
1301 : struct GNUNET_TIME_Timestamp anchor_start,
1302 : struct GNUNET_TIME_Timestamp anchor_end)
1303 : {
1304 : struct DenominationKey *dk;
1305 :
1306 236 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1307 : "Creating new key for `%s' with start date %s\n",
1308 : denom->section,
1309 : GNUNET_TIME_timestamp2s (anchor_start));
1310 236 : dk = GNUNET_new (struct DenominationKey);
1311 236 : dk->denom = denom;
1312 236 : dk->anchor_start = anchor_start;
1313 236 : dk->anchor_end = anchor_end;
1314 236 : if (GNUNET_OK !=
1315 236 : setup_key (dk,
1316 : denom->keys_tail))
1317 : {
1318 0 : GNUNET_break (0);
1319 0 : GNUNET_free (dk);
1320 0 : GNUNET_SCHEDULER_shutdown ();
1321 0 : globals->global_ret = EXIT_FAILURE;
1322 0 : return GNUNET_SYSERR;
1323 : }
1324 236 : return GNUNET_OK;
1325 : }
1326 :
1327 :
1328 : /**
1329 : * Obtain the maximum withdraw duration of all denominations.
1330 : *
1331 : * Must only be called while the #keys_lock is held.
1332 : *
1333 : * @return maximum withdraw duration, zero if there are no denominations
1334 : */
1335 : static struct GNUNET_TIME_Relative
1336 64 : get_maximum_duration (void)
1337 : {
1338 64 : struct GNUNET_TIME_Relative ret
1339 : = GNUNET_TIME_UNIT_ZERO;
1340 :
1341 64 : for (struct Denomination *denom = denom_head;
1342 309 : NULL != denom;
1343 245 : denom = denom->next)
1344 : {
1345 245 : ret = GNUNET_TIME_relative_max (ret,
1346 : denom->duration_withdraw);
1347 : }
1348 64 : return ret;
1349 : }
1350 :
1351 :
1352 : /**
1353 : * At what time do we need to next create keys if we just did?
1354 : *
1355 : * @return time when to next create keys if we just finished key generation
1356 : */
1357 : static struct GNUNET_TIME_Absolute
1358 20 : action_time (void)
1359 : {
1360 20 : struct GNUNET_TIME_Relative md = get_maximum_duration ();
1361 20 : struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1362 : uint64_t mod;
1363 :
1364 20 : if (GNUNET_TIME_relative_is_zero (md))
1365 0 : return GNUNET_TIME_UNIT_FOREVER_ABS;
1366 20 : mod = now.abs_value_us % md.rel_value_us;
1367 20 : now.abs_value_us -= mod;
1368 20 : return GNUNET_TIME_absolute_add (now,
1369 : md);
1370 : }
1371 :
1372 :
1373 : /**
1374 : * Remove all denomination keys of @a denom that have expired.
1375 : *
1376 : * @param[in,out] denom denomination family to remove keys for
1377 : */
1378 : static void
1379 324 : remove_expired_denomination_keys (struct Denomination *denom)
1380 : {
1381 576 : while ( (NULL != denom->keys_head) &&
1382 250 : GNUNET_TIME_absolute_is_past (
1383 250 : denom->keys_head->anchor_end.abs_time))
1384 : {
1385 2 : struct DenominationKey *key = denom->keys_head;
1386 2 : struct DenominationKey *nxt = key->next;
1387 :
1388 2 : if (0 != key->rc)
1389 0 : break; /* later */
1390 2 : GNUNET_CONTAINER_DLL_remove (denom->keys_head,
1391 : denom->keys_tail,
1392 : key);
1393 2 : GNUNET_assert (GNUNET_OK ==
1394 : GNUNET_CONTAINER_multihashmap_remove (
1395 : keys,
1396 : &key->h_rsa.hash,
1397 : key));
1398 4 : if ( (! key->purge) &&
1399 2 : (0 != unlink (key->filename)) )
1400 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1401 : "unlink",
1402 : key->filename);
1403 2 : GNUNET_free (key->filename);
1404 2 : GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
1405 2 : GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
1406 2 : GNUNET_free (key->an);
1407 2 : GNUNET_free (key);
1408 2 : key = nxt;
1409 : }
1410 324 : }
1411 :
1412 :
1413 : /**
1414 : * Obtain the end anchor to use at this point. Uses the
1415 : * #lookahead_sign and then rounds it up by the maximum
1416 : * duration of any denomination to arrive at a globally
1417 : * valid end-date.
1418 : *
1419 : * Must only be called while the #keys_lock is held.
1420 : *
1421 : * @return end anchor
1422 : */
1423 : static struct GNUNET_TIME_Timestamp
1424 44 : get_anchor_end (void)
1425 : {
1426 44 : struct GNUNET_TIME_Relative md = get_maximum_duration ();
1427 : struct GNUNET_TIME_Absolute end
1428 44 : = GNUNET_TIME_relative_to_absolute (lookahead_sign);
1429 : uint64_t mod;
1430 :
1431 44 : if (GNUNET_TIME_relative_is_zero (md))
1432 8 : return GNUNET_TIME_UNIT_ZERO_TS;
1433 : /* Round up 'end' to a multiple of 'md' */
1434 36 : mod = end.abs_value_us % md.rel_value_us;
1435 36 : end.abs_value_us -= mod;
1436 36 : return GNUNET_TIME_absolute_to_timestamp (
1437 : GNUNET_TIME_absolute_add (end,
1438 : md));
1439 : }
1440 :
1441 :
1442 : /**
1443 : * Create all denomination keys that are required for our
1444 : * desired lookahead and that we do not yet have.
1445 : *
1446 : * @param[in,out] opt our options
1447 : * @param[in,out] wake set to true if we should wake the clients
1448 : */
1449 : static void
1450 44 : create_missing_keys (struct TALER_SECMOD_Options *opt,
1451 : bool *wake)
1452 : {
1453 : struct GNUNET_TIME_Timestamp start;
1454 : struct GNUNET_TIME_Timestamp end;
1455 :
1456 44 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457 : "Updating denominations ...\n");
1458 44 : start = opt->global_now;
1459 44 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
1460 44 : end = get_anchor_end ();
1461 44 : for (struct Denomination *denom = denom_head;
1462 206 : NULL != denom;
1463 162 : denom = denom->next)
1464 : {
1465 : struct GNUNET_TIME_Timestamp anchor_start;
1466 : struct GNUNET_TIME_Timestamp anchor_end;
1467 : struct GNUNET_TIME_Timestamp next_end;
1468 162 : bool finished = false;
1469 :
1470 162 : remove_expired_denomination_keys (denom);
1471 162 : if (NULL != denom->keys_tail)
1472 : {
1473 86 : anchor_start = denom->keys_tail->anchor_end;
1474 86 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1475 : "Expanding keys of denomination `%s', last key %s valid for another %s\n",
1476 : denom->section,
1477 : GNUNET_h2s (&denom->keys_tail->h_rsa.hash),
1478 : GNUNET_TIME_relative2s (
1479 : GNUNET_TIME_absolute_get_remaining (
1480 : anchor_start.abs_time),
1481 : true));
1482 : }
1483 : else
1484 : {
1485 76 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1486 : "Starting keys of denomination `%s'\n",
1487 : denom->section);
1488 : /* Round the very first anchor down to the configured calendar
1489 : interval; subsequent anchors inherit the alignment from the
1490 : (rounded up) end of the preceding key. The UTC variants are used
1491 : so that the result does not depend on the time zone the secmod
1492 : happens to run in. */
1493 76 : anchor_start = GNUNET_TIME_absolute_to_timestamp (
1494 : GNUNET_TIME_round_down_utc (start.abs_time,
1495 : denom->anchor_round));
1496 : }
1497 162 : finished = GNUNET_TIME_timestamp_cmp (anchor_start,
1498 : >=,
1499 : end);
1500 398 : while (! finished)
1501 : {
1502 : /* Round the end of the validity period up to the configured calendar
1503 : interval. As #GNUNET_TIME_UNIT_YEARS is 365 days, this is also what
1504 : keeps the anchors from drifting off the calendar boundary across leap
1505 : years. Without ANCHOR_ROUND, all of this is a no-op. */
1506 236 : anchor_end = GNUNET_TIME_absolute_to_timestamp (
1507 : GNUNET_TIME_round_up_utc (
1508 : GNUNET_TIME_absolute_add (anchor_start.abs_time,
1509 : denom->duration_withdraw),
1510 : denom->anchor_round));
1511 236 : next_end = GNUNET_TIME_absolute_to_timestamp (
1512 : GNUNET_TIME_round_up_utc (
1513 : GNUNET_TIME_absolute_add (anchor_end.abs_time,
1514 : denom->duration_withdraw),
1515 : denom->anchor_round));
1516 236 : if (GNUNET_TIME_timestamp_cmp (next_end,
1517 : >,
1518 : end))
1519 : {
1520 : /* With ANCHOR_ROUND set the calendar interval already provides the
1521 : alignment, and stretching the last key would make it cover more
1522 : than the one interval it is supposed to cover. */
1523 80 : if (GNUNET_TIME_RI_NONE == denom->anchor_round)
1524 79 : anchor_end = end; /* extend period to align end periods */
1525 80 : finished = true;
1526 : }
1527 : /* adjust start time down to ensure overlap */
1528 236 : anchor_start = GNUNET_TIME_absolute_to_timestamp (
1529 : GNUNET_TIME_absolute_subtract (anchor_start.abs_time,
1530 : overlap_duration));
1531 236 : if (! *wake)
1532 : {
1533 4 : key_gen++;
1534 4 : *wake = true;
1535 : }
1536 236 : if (GNUNET_OK !=
1537 236 : create_key (denom,
1538 : anchor_start,
1539 : anchor_end))
1540 : {
1541 0 : GNUNET_break (0);
1542 0 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1543 0 : globals->global_ret = EXIT_FAILURE;
1544 0 : GNUNET_SCHEDULER_shutdown ();
1545 0 : return;
1546 : }
1547 236 : anchor_start = anchor_end;
1548 : }
1549 162 : remove_expired_denomination_keys (denom);
1550 : }
1551 44 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
1552 44 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1553 : "Updating denominations finished ...\n");
1554 : }
1555 :
1556 :
1557 : /**
1558 : * Task run periodically to expire keys and/or generate fresh ones.
1559 : *
1560 : * @param cls the `struct TALER_SECMOD_Options *`
1561 : */
1562 : static void
1563 20 : update_denominations (void *cls)
1564 : {
1565 20 : struct TALER_SECMOD_Options *opt = cls;
1566 : struct GNUNET_TIME_Absolute at;
1567 20 : bool wake = false;
1568 :
1569 : (void) cls;
1570 20 : keygen_task = NULL;
1571 : /* update current time, global override no longer applies */
1572 20 : opt->global_now = GNUNET_TIME_timestamp_get ();
1573 20 : create_missing_keys (opt,
1574 : &wake);
1575 20 : if (wake)
1576 4 : TES_wake_clients ();
1577 20 : at = action_time ();
1578 20 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1579 : "Next key generation due at %s\n",
1580 : GNUNET_TIME_absolute2s (at));
1581 20 : keygen_task = GNUNET_SCHEDULER_add_at (at,
1582 : &update_denominations,
1583 : opt);
1584 20 : }
1585 :
1586 :
1587 : /**
1588 : * Parse private key of denomination @a denom in @a buf.
1589 : *
1590 : * @param[out] denom denomination of the key
1591 : * @param filename name of the file we are parsing, for logging
1592 : * @param buf key material
1593 : * @param buf_size number of bytes in @a buf
1594 : */
1595 : static void
1596 9 : parse_key (struct Denomination *denom,
1597 : const char *filename,
1598 : const void *buf,
1599 : size_t buf_size)
1600 : {
1601 : struct GNUNET_CRYPTO_RsaPrivateKey *priv;
1602 : const char *anchor_s;
1603 : char dummy;
1604 : unsigned long long anchor_start_ll;
1605 : unsigned long long anchor_end_ll;
1606 : struct GNUNET_TIME_Timestamp anchor_start;
1607 : struct GNUNET_TIME_Timestamp anchor_end;
1608 9 : char *nf = NULL;
1609 :
1610 9 : anchor_s = strrchr (filename,
1611 : '/');
1612 9 : if (NULL == anchor_s)
1613 : {
1614 : /* File in a directory without '/' in the name, this makes no sense. */
1615 0 : GNUNET_break (0);
1616 0 : return;
1617 : }
1618 9 : anchor_s++;
1619 9 : if (2 != sscanf (anchor_s,
1620 : "%llu-%llu%c",
1621 : &anchor_start_ll,
1622 : &anchor_end_ll,
1623 : &dummy))
1624 : {
1625 : /* try legacy mode */
1626 3 : if (1 != sscanf (anchor_s,
1627 : "%llu%c",
1628 : &anchor_start_ll,
1629 : &dummy))
1630 : {
1631 : /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
1632 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1633 : "Filename `%s' invalid for key file, skipping\n",
1634 : anchor_s);
1635 0 : return;
1636 : }
1637 : anchor_start.abs_time.abs_value_us
1638 3 : = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1639 6 : if (anchor_start_ll != anchor_start.abs_time.abs_value_us
1640 3 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
1641 : {
1642 : /* Integer overflow. Bad, invalid filename. */
1643 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1644 : "Integer overflow. Filename `%s' invalid for key file, skipping\n",
1645 : anchor_s);
1646 0 : return;
1647 : }
1648 : anchor_end
1649 3 : = GNUNET_TIME_absolute_to_timestamp (
1650 : GNUNET_TIME_absolute_add (anchor_start.abs_time,
1651 : denom->duration_withdraw));
1652 3 : GNUNET_asprintf (
1653 : &nf,
1654 : "%s/%s/%llu-%llu",
1655 : keydir,
1656 : denom->section,
1657 : anchor_start_ll,
1658 3 : (unsigned long long) (anchor_end.abs_time.abs_value_us
1659 3 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1660 : /* Try to fix the legacy filename */
1661 3 : if (0 !=
1662 3 : rename (filename,
1663 : nf))
1664 : {
1665 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1666 : "rename",
1667 : filename);
1668 0 : GNUNET_free (nf);
1669 : }
1670 : }
1671 : else
1672 : {
1673 : anchor_start.abs_time.abs_value_us
1674 6 : = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1675 : anchor_end.abs_time.abs_value_us
1676 6 : = anchor_end_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1677 12 : if ( (anchor_start_ll != anchor_start.abs_time.abs_value_us
1678 6 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us) ||
1679 12 : (anchor_end_ll != anchor_end.abs_time.abs_value_us
1680 6 : / GNUNET_TIME_UNIT_SECONDS.rel_value_us) )
1681 : {
1682 : /* Integer overflow. Bad, invalid filename. */
1683 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1684 : "Integer overflow. Filename `%s' invalid for key file, skipping\n",
1685 : anchor_s);
1686 0 : return;
1687 : }
1688 : }
1689 9 : priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
1690 : buf_size);
1691 9 : if (NULL == priv)
1692 : {
1693 : /* Parser failure. */
1694 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1695 : "File `%s' is malformed, skipping\n",
1696 : (NULL == nf) ? filename : nf);
1697 0 : GNUNET_free (nf);
1698 0 : return;
1699 : }
1700 :
1701 : {
1702 : struct GNUNET_CRYPTO_RsaPublicKey *pub;
1703 : struct DenominationKey *dk;
1704 : struct DenominationKey *before;
1705 :
1706 9 : pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
1707 9 : if (NULL == pub)
1708 : {
1709 0 : GNUNET_break (0);
1710 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
1711 0 : GNUNET_free (nf);
1712 0 : return;
1713 : }
1714 : /* refuse keys whose modulus does not have the configured size */
1715 9 : if (denom->rsa_keysize !=
1716 9 : GNUNET_CRYPTO_rsa_public_key_len (pub))
1717 : {
1718 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1719 : "File `%s' holds a %u-bit RSA key, but RSA_KEYSIZE of section `%s' is %u; refusing to use it\n",
1720 : (NULL == nf) ? filename : nf,
1721 : GNUNET_CRYPTO_rsa_public_key_len (pub),
1722 : denom->section,
1723 : (unsigned int) denom->rsa_keysize);
1724 0 : GNUNET_CRYPTO_rsa_public_key_free (pub);
1725 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
1726 0 : GNUNET_free (nf);
1727 0 : return;
1728 : }
1729 9 : dk = GNUNET_new (struct DenominationKey);
1730 9 : dk->denom_priv = priv;
1731 9 : dk->denom = denom;
1732 9 : dk->anchor_start = anchor_start;
1733 9 : dk->anchor_end = anchor_end;
1734 9 : dk->filename = (NULL == nf) ? GNUNET_strdup (filename) : nf;
1735 9 : GNUNET_CRYPTO_rsa_public_key_hash (pub,
1736 : &dk->h_rsa.hash);
1737 9 : dk->denom_pub = pub;
1738 9 : generate_response (dk);
1739 9 : if (GNUNET_OK !=
1740 9 : GNUNET_CONTAINER_multihashmap_put (
1741 : keys,
1742 9 : &dk->h_rsa.hash,
1743 : dk,
1744 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1745 : {
1746 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1747 : "Duplicate private key %s detected in file `%s'. Skipping.\n",
1748 : GNUNET_h2s (&dk->h_rsa.hash),
1749 : filename);
1750 0 : GNUNET_CRYPTO_rsa_private_key_free (priv);
1751 0 : GNUNET_CRYPTO_rsa_public_key_free (pub);
1752 0 : GNUNET_free (dk->an);
1753 0 : GNUNET_free (dk);
1754 0 : return;
1755 : }
1756 9 : before = NULL;
1757 9 : for (struct DenominationKey *pos = denom->keys_head;
1758 10 : NULL != pos;
1759 1 : pos = pos->next)
1760 : {
1761 6 : if (GNUNET_TIME_timestamp_cmp (pos->anchor_start,
1762 : >,
1763 : anchor_start))
1764 5 : break;
1765 1 : before = pos;
1766 : }
1767 9 : GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
1768 : denom->keys_tail,
1769 : before,
1770 : dk);
1771 9 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1772 : "Imported key %s from `%s'\n",
1773 : GNUNET_h2s (&dk->h_rsa.hash),
1774 : filename);
1775 : }
1776 : }
1777 :
1778 :
1779 : /**
1780 : * Import a private key from @a filename for the denomination
1781 : * given in @a cls.
1782 : *
1783 : * @param[in,out] cls a `struct Denomiantion`
1784 : * @param filename name of a file in the directory
1785 : * @return #GNUNET_OK (always, continue to iterate)
1786 : */
1787 : static enum GNUNET_GenericReturnValue
1788 9 : import_key (void *cls,
1789 : const char *filename)
1790 : {
1791 9 : struct Denomination *denom = cls;
1792 : struct GNUNET_DISK_FileHandle *fh;
1793 : struct GNUNET_DISK_MapHandle *map;
1794 : void *ptr;
1795 : int fd;
1796 : struct stat sbuf;
1797 :
1798 9 : fd = TES_open_key_file (filename,
1799 : &sbuf);
1800 9 : if (-1 == fd)
1801 0 : return GNUNET_OK;
1802 9 : fh = GNUNET_DISK_get_handle_from_int_fd (fd);
1803 9 : if (NULL == fh)
1804 : {
1805 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1806 : "open",
1807 : filename);
1808 0 : GNUNET_break (0 == close (fd));
1809 0 : return GNUNET_OK;
1810 : }
1811 9 : if (sbuf.st_size > 16 * 1024)
1812 : {
1813 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1814 : "File `%s' too big to be a private key\n",
1815 : filename);
1816 0 : GNUNET_DISK_file_close (fh);
1817 0 : return GNUNET_OK;
1818 : }
1819 9 : ptr = GNUNET_DISK_file_map (fh,
1820 : &map,
1821 : GNUNET_DISK_MAP_TYPE_READ,
1822 9 : (size_t) sbuf.st_size);
1823 9 : if (NULL == ptr)
1824 : {
1825 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1826 : "mmap",
1827 : filename);
1828 0 : GNUNET_DISK_file_close (fh);
1829 0 : return GNUNET_OK;
1830 : }
1831 9 : parse_key (denom,
1832 : filename,
1833 : ptr,
1834 9 : (size_t) sbuf.st_size);
1835 9 : GNUNET_DISK_file_unmap (map);
1836 9 : GNUNET_DISK_file_close (fh);
1837 9 : return GNUNET_OK;
1838 : }
1839 :
1840 :
1841 : /**
1842 : * Parse configuration for denomination type parameters. Also determines
1843 : * our anchor by looking at the existing denominations of the same type.
1844 : *
1845 : * @param cfg configuration to use
1846 : * @param ct section in the configuration file giving the denomination type parameters
1847 : * @param[out] denom set to the denomination parameters from the configuration
1848 : * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
1849 : */
1850 : static enum GNUNET_GenericReturnValue
1851 79 : parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
1852 : const char *ct,
1853 : struct Denomination *denom)
1854 : {
1855 : unsigned long long rsa_keysize;
1856 : char *secname;
1857 :
1858 79 : GNUNET_asprintf (&secname,
1859 : "%s-secmod-rsa",
1860 79 : globals->section);
1861 79 : if (GNUNET_OK !=
1862 79 : GNUNET_CONFIGURATION_get_value_time (cfg,
1863 : ct,
1864 : "DURATION_WITHDRAW",
1865 : &denom->duration_withdraw))
1866 : {
1867 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1868 : ct,
1869 : "DURATION_WITHDRAW");
1870 0 : GNUNET_free (secname);
1871 0 : return GNUNET_SYSERR;
1872 : }
1873 79 : if (GNUNET_TIME_relative_cmp (denom->duration_withdraw,
1874 : <,
1875 : GNUNET_TIME_UNIT_SECONDS))
1876 : {
1877 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1878 : ct,
1879 : "DURATION_WITHDRAW",
1880 : "less than one second is not supported");
1881 0 : GNUNET_free (secname);
1882 0 : return GNUNET_SYSERR;
1883 : }
1884 79 : if (GNUNET_TIME_relative_cmp (overlap_duration,
1885 : >=,
1886 : denom->duration_withdraw))
1887 : {
1888 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1889 : secname,
1890 : "OVERLAP_DURATION",
1891 : "Value given must be smaller than value for DURATION_WITHDRAW!");
1892 0 : GNUNET_free (secname);
1893 0 : return GNUNET_SYSERR;
1894 : }
1895 : {
1896 : struct GNUNET_TIME_Relative ar;
1897 :
1898 : /* The denomination section takes precedence, the secmod section
1899 : provides the default for all denominations. */
1900 79 : if ( (GNUNET_OK !=
1901 79 : GNUNET_CONFIGURATION_get_value_time (cfg,
1902 : ct,
1903 : "ANCHOR_ROUND",
1904 75 : &ar)) &&
1905 : (GNUNET_OK !=
1906 75 : GNUNET_CONFIGURATION_get_value_time (cfg,
1907 : secname,
1908 : "ANCHOR_ROUND",
1909 : &ar)) )
1910 0 : ar = GNUNET_TIME_UNIT_ZERO; /* not configured: do not round */
1911 : denom->anchor_round
1912 79 : = GNUNET_TIME_relative_to_round_interval (ar);
1913 79 : if ( (GNUNET_TIME_RI_NONE == denom->anchor_round) &&
1914 75 : (! GNUNET_TIME_relative_is_zero (ar)) )
1915 : {
1916 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1917 : ct,
1918 : "ANCHOR_ROUND",
1919 : "Value given must be zero or exactly one second, minute, hour, day, week, month, quarter or year");
1920 0 : GNUNET_free (secname);
1921 0 : return GNUNET_SYSERR;
1922 : }
1923 : }
1924 79 : if (GNUNET_OK !=
1925 79 : GNUNET_CONFIGURATION_get_value_number (cfg,
1926 : ct,
1927 : "RSA_KEYSIZE",
1928 : &rsa_keysize))
1929 : {
1930 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1931 : ct,
1932 : "RSA_KEYSIZE");
1933 0 : GNUNET_free (secname);
1934 0 : return GNUNET_SYSERR;
1935 : }
1936 79 : if ( (rsa_keysize > 4 * 2048) ||
1937 79 : (rsa_keysize < 1024) )
1938 : {
1939 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1940 : ct,
1941 : "RSA_KEYSIZE",
1942 : "Given RSA keysize outside of permitted range [1024,8192]\n");
1943 0 : GNUNET_free (secname);
1944 0 : return GNUNET_SYSERR;
1945 : }
1946 79 : GNUNET_free (secname);
1947 79 : denom->rsa_keysize = (unsigned int) rsa_keysize;
1948 79 : denom->section = TES_normalize_section (ct);
1949 79 : return GNUNET_OK;
1950 : }
1951 :
1952 :
1953 : /**
1954 : * Closure for #load_denominations.
1955 : */
1956 : struct LoadContext
1957 : {
1958 :
1959 : /**
1960 : * Configuration to use.
1961 : */
1962 : const struct GNUNET_CONFIGURATION_Handle *cfg;
1963 :
1964 : /**
1965 : * Configuration section prefix to use for denomination settings.
1966 : * "coin_" for the exchange, "doco_" for Donau.
1967 : */
1968 : const char *cprefix;
1969 :
1970 : /**
1971 : * Status, to be set to #GNUNET_SYSERR on failure
1972 : */
1973 : enum GNUNET_GenericReturnValue ret;
1974 : };
1975 :
1976 :
1977 : /**
1978 : * Generate new denomination signing keys for the denomination type of the given @a
1979 : * denomination_alias.
1980 : *
1981 : * @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure
1982 : * @param denomination_alias name of the denomination's section in the configuration
1983 : */
1984 : static void
1985 1027 : load_denominations (void *cls,
1986 : const char *denomination_alias)
1987 : {
1988 1027 : struct LoadContext *ctx = cls;
1989 : struct Denomination *denom;
1990 : char *cipher;
1991 :
1992 1027 : if (0 != strncasecmp (denomination_alias,
1993 : ctx->cprefix,
1994 : strlen (ctx->cprefix)))
1995 948 : return; /* not a denomination type definition */
1996 141 : if (GNUNET_OK !=
1997 141 : GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
1998 : denomination_alias,
1999 : "CIPHER",
2000 : &cipher))
2001 : {
2002 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2003 : denomination_alias,
2004 : "CIPHER");
2005 0 : return;
2006 : }
2007 141 : if (0 != strcmp (cipher,
2008 : "RSA"))
2009 : {
2010 62 : GNUNET_free (cipher);
2011 62 : return; /* Ignore denominations of other types than CS */
2012 : }
2013 79 : GNUNET_free (cipher);
2014 79 : denom = GNUNET_new (struct Denomination);
2015 79 : if (GNUNET_OK !=
2016 79 : parse_denomination_cfg (ctx->cfg,
2017 : denomination_alias,
2018 : denom))
2019 : {
2020 0 : ctx->ret = GNUNET_SYSERR;
2021 0 : GNUNET_free (denom);
2022 0 : return;
2023 : }
2024 79 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2025 : "Loading keys for denomination %s\n",
2026 : denom->section);
2027 : {
2028 : char *dname;
2029 :
2030 79 : GNUNET_asprintf (&dname,
2031 : "%s/%s",
2032 : keydir,
2033 : denom->section);
2034 79 : GNUNET_break (GNUNET_OK ==
2035 : GNUNET_DISK_directory_create (dname));
2036 79 : GNUNET_DISK_directory_scan (dname,
2037 : &import_key,
2038 : denom);
2039 79 : GNUNET_free (dname);
2040 : }
2041 79 : GNUNET_CONTAINER_DLL_insert (denom_head,
2042 : denom_tail,
2043 : denom);
2044 : }
2045 :
2046 :
2047 : /**
2048 : * Load the various duration values from @a cfg
2049 : *
2050 : * @param cfg configuration to use
2051 : * @return #GNUNET_OK on success
2052 : */
2053 : static enum GNUNET_GenericReturnValue
2054 37 : load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
2055 : {
2056 : char *secname;
2057 :
2058 37 : GNUNET_asprintf (&secname,
2059 : "%s-secmod-rsa",
2060 37 : globals->section);
2061 37 : if (GNUNET_OK !=
2062 37 : GNUNET_CONFIGURATION_get_value_time (cfg,
2063 : secname,
2064 : "OVERLAP_DURATION",
2065 : &overlap_duration))
2066 : {
2067 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2068 : secname,
2069 : "OVERLAP_DURATION");
2070 0 : GNUNET_free (secname);
2071 0 : return GNUNET_SYSERR;
2072 : }
2073 37 : if (GNUNET_OK !=
2074 37 : GNUNET_CONFIGURATION_get_value_time (cfg,
2075 : secname,
2076 : "LOOKAHEAD_SIGN",
2077 : &lookahead_sign))
2078 : {
2079 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2080 : secname,
2081 : "LOOKAHEAD_SIGN");
2082 0 : GNUNET_free (secname);
2083 0 : return GNUNET_SYSERR;
2084 : }
2085 37 : GNUNET_free (secname);
2086 37 : return GNUNET_OK;
2087 : }
2088 :
2089 :
2090 : /**
2091 : * Function run on shutdown. Stops the various jobs (nicely).
2092 : *
2093 : * @param cls NULL
2094 : */
2095 : static void
2096 24 : do_shutdown (void *cls)
2097 : {
2098 : (void) cls;
2099 24 : TES_listen_stop ();
2100 24 : if (NULL != keygen_task)
2101 : {
2102 16 : GNUNET_SCHEDULER_cancel (keygen_task);
2103 16 : keygen_task = NULL;
2104 : }
2105 24 : stop_workers ();
2106 24 : sem_done (&worker_sem);
2107 24 : }
2108 :
2109 :
2110 : void
2111 37 : TALER_SECMOD_rsa_run (void *cls,
2112 : char *const *args,
2113 : const char *cfgfile,
2114 : const struct GNUNET_CONFIGURATION_Handle *cfg)
2115 : {
2116 : static struct TES_Callbacks cb = {
2117 : .dispatch = rsa_work_dispatch,
2118 : .updater = rsa_update_client_keys,
2119 : .init = rsa_client_init
2120 : };
2121 37 : struct TALER_SECMOD_Options *opt = cls;
2122 : char *secname;
2123 :
2124 : (void) args;
2125 : (void) cfgfile;
2126 37 : globals = opt;
2127 37 : if (GNUNET_TIME_timestamp_cmp (opt->global_now,
2128 : !=,
2129 : opt->global_now_tmp))
2130 : {
2131 : /* The user gave "--now", use it! */
2132 0 : opt->global_now = opt->global_now_tmp;
2133 : }
2134 : else
2135 : {
2136 : /* get current time again, we may be timetraveling! */
2137 37 : opt->global_now = GNUNET_TIME_timestamp_get ();
2138 : }
2139 37 : GNUNET_asprintf (&secname,
2140 : "%s-secmod-rsa",
2141 : opt->section);
2142 37 : if (GNUNET_OK !=
2143 37 : GNUNET_CONFIGURATION_get_value_filename (cfg,
2144 : secname,
2145 : "KEY_DIR",
2146 : &keydir))
2147 : {
2148 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2149 : secname,
2150 : "KEY_DIR");
2151 0 : GNUNET_free (secname);
2152 0 : opt->global_ret = EXIT_NOTCONFIGURED;
2153 21 : return;
2154 : }
2155 37 : if (GNUNET_OK !=
2156 37 : load_durations (cfg))
2157 : {
2158 0 : opt->global_ret = EXIT_NOTCONFIGURED;
2159 0 : GNUNET_free (secname);
2160 0 : return;
2161 : }
2162 37 : if (GNUNET_OK !=
2163 37 : TES_normalize_key_directory (cfg,
2164 : keydir,
2165 : opt->cprefix))
2166 : {
2167 13 : opt->global_ret = EXIT_FAILURE;
2168 13 : GNUNET_free (secname);
2169 13 : return;
2170 : }
2171 24 : opt->global_ret = TES_listen_start (cfg,
2172 : secname,
2173 : &cb);
2174 24 : GNUNET_free (secname);
2175 24 : if (0 != opt->global_ret)
2176 0 : return;
2177 24 : sem_init (&worker_sem,
2178 : 0);
2179 24 : GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
2180 : NULL);
2181 24 : if (0 == opt->max_workers)
2182 : {
2183 : long lret;
2184 :
2185 0 : lret = sysconf (_SC_NPROCESSORS_CONF);
2186 0 : if (lret <= 0)
2187 0 : lret = 1;
2188 0 : opt->max_workers = (unsigned int) lret;
2189 : }
2190 :
2191 348 : for (unsigned int i = 0; i<opt->max_workers; i++)
2192 324 : if (GNUNET_OK !=
2193 324 : start_worker ())
2194 : {
2195 0 : GNUNET_SCHEDULER_shutdown ();
2196 0 : return;
2197 : }
2198 : /* Load denominations */
2199 24 : keys = GNUNET_CONTAINER_multihashmap_create (65536,
2200 : true);
2201 : {
2202 24 : struct LoadContext lc = {
2203 : .cfg = cfg,
2204 : .ret = GNUNET_OK,
2205 24 : .cprefix = opt->cprefix
2206 : };
2207 24 : bool wake = true;
2208 :
2209 24 : GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
2210 24 : GNUNET_CONFIGURATION_iterate_sections (cfg,
2211 : &load_denominations,
2212 : &lc);
2213 24 : GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
2214 24 : if (GNUNET_OK != lc.ret)
2215 : {
2216 0 : opt->global_ret = EXIT_FAILURE;
2217 0 : GNUNET_SCHEDULER_shutdown ();
2218 0 : return;
2219 : }
2220 24 : create_missing_keys (opt,
2221 : &wake);
2222 : }
2223 24 : if (NULL == denom_head)
2224 : {
2225 8 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2226 : "No RSA denominations configured. Make sure section names start with `%s' if you are using RSA!\n",
2227 : opt->cprefix);
2228 8 : TES_wake_clients ();
2229 8 : return;
2230 : }
2231 : /* start job to keep keys up-to-date; MUST be run before the #listen_task,
2232 : hence with priority. */
2233 16 : keygen_task = GNUNET_SCHEDULER_add_with_priority (
2234 : GNUNET_SCHEDULER_PRIORITY_URGENT,
2235 : &update_denominations,
2236 : opt);
2237 : }
|