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