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