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