crypto_helper_rsa.c (26604B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2020, 2021 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/crypto_helper_rsa.c 18 * @brief utility functions for running out-of-process private key operations 19 * @author Christian Grothoff 20 */ 21 #include "taler/platform.h" 22 #include "taler/taler_util.h" 23 #include "taler/taler_signatures.h" 24 #include "crypto_helper_common.h" 25 #include "secmod_rsa.h" 26 #include <poll.h> 27 28 29 struct TALER_CRYPTO_RsaDenominationHelper 30 { 31 /** 32 * Function to call with updates to available key material. 33 */ 34 TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc; 35 36 /** 37 * Closure for @e dkc 38 */ 39 void *dkc_cls; 40 41 /** 42 * Socket address of the denomination helper process. 43 * Used to reconnect if the connection breaks. 44 */ 45 struct sockaddr_un sa; 46 47 /** 48 * The UNIX domain socket, -1 if we are currently not connected. 49 */ 50 int sock; 51 52 /** 53 * Have we ever been sync'ed? 54 */ 55 bool synced; 56 }; 57 58 59 /** 60 * Disconnect from the helper process. Updates 61 * @e sock field in @a dh. 62 * 63 * @param[in,out] dh handle to tear down connection of 64 */ 65 static void 66 do_disconnect (struct TALER_CRYPTO_RsaDenominationHelper *dh) 67 { 68 GNUNET_break (0 == close (dh->sock)); 69 dh->sock = -1; 70 dh->synced = false; 71 } 72 73 74 /** 75 * Try to connect to the helper process. Updates 76 * @e sock field in @a dh. 77 * 78 * @param[in,out] dh handle to establish connection for 79 * @return #GNUNET_OK on success 80 */ 81 static enum GNUNET_GenericReturnValue 82 try_connect (struct TALER_CRYPTO_RsaDenominationHelper *dh) 83 { 84 if (-1 != dh->sock) 85 return GNUNET_OK; 86 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 87 "Establishing connection!\n"); 88 dh->sock = socket (AF_UNIX, 89 SOCK_STREAM, 90 0); 91 if (-1 == dh->sock) 92 { 93 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 94 "socket"); 95 return GNUNET_SYSERR; 96 } 97 if (0 != 98 connect (dh->sock, 99 (const struct sockaddr *) &dh->sa, 100 sizeof (dh->sa))) 101 { 102 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 103 "connect", 104 dh->sa.sun_path); 105 do_disconnect (dh); 106 return GNUNET_SYSERR; 107 } 108 TALER_CRYPTO_helper_rsa_poll (dh); 109 return GNUNET_OK; 110 } 111 112 113 struct TALER_CRYPTO_RsaDenominationHelper * 114 TALER_CRYPTO_helper_rsa_connect ( 115 const struct GNUNET_CONFIGURATION_Handle *cfg, 116 const char *section, 117 TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc, 118 void *dkc_cls) 119 { 120 struct TALER_CRYPTO_RsaDenominationHelper *dh; 121 char *unixpath; 122 char *secname; 123 124 GNUNET_asprintf (&secname, 125 "%s-secmod-rsa", 126 section); 127 128 if (GNUNET_OK != 129 GNUNET_CONFIGURATION_get_value_filename (cfg, 130 secname, 131 "UNIXPATH", 132 &unixpath)) 133 { 134 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 135 secname, 136 "UNIXPATH"); 137 GNUNET_free (secname); 138 return NULL; 139 } 140 /* we use >= here because we want the sun_path to always 141 be 0-terminated */ 142 if (strlen (unixpath) >= sizeof (dh->sa.sun_path)) 143 { 144 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 145 secname, 146 "UNIXPATH", 147 "path too long"); 148 GNUNET_free (unixpath); 149 GNUNET_free (secname); 150 return NULL; 151 } 152 GNUNET_free (secname); 153 dh = GNUNET_new (struct TALER_CRYPTO_RsaDenominationHelper); 154 dh->dkc = dkc; 155 dh->dkc_cls = dkc_cls; 156 dh->sa.sun_family = AF_UNIX; 157 strncpy (dh->sa.sun_path, 158 unixpath, 159 sizeof (dh->sa.sun_path) - 1); 160 GNUNET_free (unixpath); 161 dh->sock = -1; 162 if (GNUNET_OK != 163 try_connect (dh)) 164 { 165 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 166 "Could not connect to %s. Will keep trying\n", 167 "taler-exchange-helper-secmod-rsa"); 168 } 169 return dh; 170 } 171 172 173 /** 174 * Handle a #TALER_HELPER_RSA_MT_AVAIL message from the helper. 175 * 176 * @param dh helper context 177 * @param hdr message that we received 178 * @return #GNUNET_OK on success 179 */ 180 static enum GNUNET_GenericReturnValue 181 handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper *dh, 182 const struct GNUNET_MessageHeader *hdr) 183 { 184 const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan 185 = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) hdr; 186 const char *buf = (const char *) &kan[1]; 187 const char *section_name; 188 uint16_t ps; 189 uint16_t snl; 190 191 if (sizeof (*kan) > ntohs (hdr->size)) 192 { 193 GNUNET_break_op (0); 194 return GNUNET_SYSERR; 195 } 196 ps = ntohs (kan->pub_size); 197 snl = ntohs (kan->section_name_len); 198 if (ntohs (hdr->size) != sizeof (*kan) + ps + snl) 199 { 200 GNUNET_break_op (0); 201 return GNUNET_SYSERR; 202 } 203 if (0 == snl) 204 { 205 GNUNET_break_op (0); 206 return GNUNET_SYSERR; 207 } 208 section_name = &buf[ps]; 209 if ('\0' != section_name[snl - 1]) 210 { 211 GNUNET_break_op (0); 212 return GNUNET_SYSERR; 213 } 214 215 { 216 struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub; 217 struct TALER_RsaPubHashP h_rsa; 218 219 bs_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 220 bs_pub->cipher = GNUNET_CRYPTO_BSA_RSA; 221 bs_pub->details.rsa_public_key 222 = GNUNET_CRYPTO_rsa_public_key_decode (buf, 223 ntohs (kan->pub_size)); 224 if (NULL == bs_pub->details.rsa_public_key) 225 { 226 GNUNET_break_op (0); 227 GNUNET_free (bs_pub); 228 return GNUNET_SYSERR; 229 } 230 bs_pub->rc = 1; 231 GNUNET_CRYPTO_rsa_public_key_hash (bs_pub->details.rsa_public_key, 232 &bs_pub->pub_key_hash); 233 h_rsa.hash = bs_pub->pub_key_hash; 234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 235 "Received RSA key %s (%s)\n", 236 GNUNET_h2s (&bs_pub->pub_key_hash), 237 section_name); 238 if (GNUNET_OK != 239 TALER_exchange_secmod_rsa_verify ( 240 &h_rsa, 241 section_name, 242 GNUNET_TIME_timestamp_ntoh (kan->anchor_time), 243 GNUNET_TIME_relative_ntoh (kan->duration_withdraw), 244 &kan->secm_pub, 245 &kan->secm_sig)) 246 { 247 GNUNET_break_op (0); 248 GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub); 249 return GNUNET_SYSERR; 250 } 251 dh->dkc (dh->dkc_cls, 252 section_name, 253 GNUNET_TIME_timestamp_ntoh (kan->anchor_time), 254 GNUNET_TIME_relative_ntoh (kan->duration_withdraw), 255 &h_rsa, 256 bs_pub, 257 &kan->secm_pub, 258 &kan->secm_sig); 259 GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub); 260 } 261 return GNUNET_OK; 262 } 263 264 265 /** 266 * Handle a #TALER_HELPER_RSA_MT_PURGE message from the helper. 267 * 268 * @param dh helper context 269 * @param hdr message that we received 270 * @return #GNUNET_OK on success 271 */ 272 static enum GNUNET_GenericReturnValue 273 handle_mt_purge (struct TALER_CRYPTO_RsaDenominationHelper *dh, 274 const struct GNUNET_MessageHeader *hdr) 275 { 276 const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn 277 = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) hdr; 278 279 if (sizeof (*pn) != ntohs (hdr->size)) 280 { 281 GNUNET_break_op (0); 282 return GNUNET_SYSERR; 283 } 284 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 285 "Received revocation of denomination key %s\n", 286 GNUNET_h2s (&pn->h_rsa.hash)); 287 dh->dkc (dh->dkc_cls, 288 NULL, 289 GNUNET_TIME_UNIT_ZERO_TS, 290 GNUNET_TIME_UNIT_ZERO, 291 &pn->h_rsa, 292 NULL, 293 NULL, 294 NULL); 295 return GNUNET_OK; 296 } 297 298 299 void 300 TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh) 301 { 302 char buf[UINT16_MAX]; 303 size_t off = 0; 304 unsigned int retry_limit = 3; 305 const struct GNUNET_MessageHeader *hdr 306 = (const struct GNUNET_MessageHeader *) buf; 307 308 if (GNUNET_OK != 309 try_connect (dh)) 310 return; /* give up */ 311 while (1) 312 { 313 uint16_t msize; 314 ssize_t ret; 315 316 ret = recv (dh->sock, 317 buf + off, 318 sizeof (buf) - off, 319 (dh->synced && (0 == off)) 320 ? MSG_DONTWAIT 321 : 0); 322 if (ret < 0) 323 { 324 if (EINTR == errno) 325 continue; 326 if (EAGAIN == errno) 327 { 328 GNUNET_assert (dh->synced); 329 GNUNET_assert (0 == off); 330 break; 331 } 332 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 333 "recv"); 334 do_disconnect (dh); 335 if (0 == retry_limit) 336 return; /* give up */ 337 if (GNUNET_OK != 338 try_connect (dh)) 339 return; /* give up */ 340 retry_limit--; 341 continue; 342 } 343 if (0 == ret) 344 { 345 GNUNET_break (0 == off); 346 return; 347 } 348 off += ret; 349 more: 350 if (off < sizeof (struct GNUNET_MessageHeader)) 351 continue; 352 msize = ntohs (hdr->size); 353 if (off < msize) 354 continue; 355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 356 "Received message of type %u and length %u\n", 357 (unsigned int) ntohs (hdr->type), 358 (unsigned int) msize); 359 switch (ntohs (hdr->type)) 360 { 361 case TALER_HELPER_RSA_MT_AVAIL: 362 if (GNUNET_OK != 363 handle_mt_avail (dh, 364 hdr)) 365 { 366 GNUNET_break_op (0); 367 do_disconnect (dh); 368 return; 369 } 370 break; 371 case TALER_HELPER_RSA_MT_PURGE: 372 if (GNUNET_OK != 373 handle_mt_purge (dh, 374 hdr)) 375 { 376 GNUNET_break_op (0); 377 do_disconnect (dh); 378 return; 379 } 380 break; 381 case TALER_HELPER_RSA_SYNCED: 382 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 383 "Now synchronized with RSA helper\n"); 384 dh->synced = true; 385 break; 386 default: 387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 388 "Received unexpected message of type %d (len: %u)\n", 389 (unsigned int) ntohs (hdr->type), 390 (unsigned int) msize); 391 GNUNET_break_op (0); 392 do_disconnect (dh); 393 return; 394 } 395 memmove (buf, 396 &buf[msize], 397 off - msize); 398 off -= msize; 399 goto more; 400 } 401 } 402 403 404 enum TALER_ErrorCode 405 TALER_CRYPTO_helper_rsa_sign ( 406 struct TALER_CRYPTO_RsaDenominationHelper *dh, 407 const struct TALER_CRYPTO_RsaSignRequest *rsr, 408 struct TALER_BlindedDenominationSignature *bs) 409 { 410 enum TALER_ErrorCode ec = TALER_EC_INVALID; 411 412 memset (bs, 413 0, 414 sizeof (*bs)); 415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 416 "Starting signature process\n"); 417 if (GNUNET_OK != 418 try_connect (dh)) 419 { 420 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 421 "Failed to connect to helper\n"); 422 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; 423 } 424 425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 426 "Requesting signature\n"); 427 { 428 char buf[sizeof (struct TALER_CRYPTO_SignRequest) + rsr->msg_size]; 429 struct TALER_CRYPTO_SignRequest *sr 430 = (struct TALER_CRYPTO_SignRequest *) buf; 431 432 sr->header.size = htons (sizeof (buf)); 433 sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN); 434 sr->reserved = htonl (0); 435 sr->h_rsa = *rsr->h_rsa; 436 GNUNET_memcpy (&sr[1], 437 rsr->msg, 438 rsr->msg_size); 439 if (GNUNET_OK != 440 TALER_crypto_helper_send_all (dh->sock, 441 buf, 442 sizeof (buf))) 443 { 444 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 445 "send"); 446 do_disconnect (dh); 447 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; 448 } 449 } 450 451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 452 "Awaiting reply\n"); 453 { 454 char buf[UINT16_MAX]; 455 size_t off = 0; 456 const struct GNUNET_MessageHeader *hdr 457 = (const struct GNUNET_MessageHeader *) buf; 458 bool finished = false; 459 460 while (1) 461 { 462 uint16_t msize; 463 ssize_t ret; 464 465 ret = recv (dh->sock, 466 &buf[off], 467 sizeof (buf) - off, 468 (finished && (0 == off)) 469 ? MSG_DONTWAIT 470 : 0); 471 if (ret < 0) 472 { 473 if (EINTR == errno) 474 continue; 475 if (EAGAIN == errno) 476 { 477 GNUNET_assert (finished); 478 GNUNET_assert (0 == off); 479 return ec; 480 } 481 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 482 "recv"); 483 do_disconnect (dh); 484 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; 485 break; 486 } 487 if (0 == ret) 488 { 489 GNUNET_break (0 == off); 490 if (! finished) 491 ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG; 492 return ec; 493 } 494 off += ret; 495 more: 496 if (off < sizeof (struct GNUNET_MessageHeader)) 497 continue; 498 msize = ntohs (hdr->size); 499 if (off < msize) 500 continue; 501 switch (ntohs (hdr->type)) 502 { 503 case TALER_HELPER_RSA_MT_RES_SIGNATURE: 504 if (msize < sizeof (struct TALER_CRYPTO_SignResponse)) 505 { 506 GNUNET_break_op (0); 507 do_disconnect (dh); 508 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 509 goto end; 510 } 511 if (finished) 512 { 513 GNUNET_break_op (0); 514 do_disconnect (dh); 515 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 516 goto end; 517 } 518 { 519 const struct TALER_CRYPTO_SignResponse *sr = 520 (const struct TALER_CRYPTO_SignResponse *) buf; 521 struct GNUNET_CRYPTO_RsaSignature *rsa_signature; 522 struct GNUNET_CRYPTO_BlindedSignature *blind_sig; 523 524 rsa_signature = GNUNET_CRYPTO_rsa_signature_decode ( 525 &sr[1], 526 msize - sizeof (*sr)); 527 if (NULL == rsa_signature) 528 { 529 GNUNET_break_op (0); 530 do_disconnect (dh); 531 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 532 goto end; 533 } 534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 535 "Received signature\n"); 536 ec = TALER_EC_NONE; 537 finished = true; 538 blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); 539 blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA; 540 blind_sig->rc = 1; 541 blind_sig->details.blinded_rsa_signature = rsa_signature; 542 bs->blinded_sig = blind_sig; 543 break; 544 } 545 case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE: 546 if (msize != sizeof (struct TALER_CRYPTO_SignFailure)) 547 { 548 GNUNET_break_op (0); 549 do_disconnect (dh); 550 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 551 goto end; 552 } 553 { 554 const struct TALER_CRYPTO_SignFailure *sf = 555 (const struct TALER_CRYPTO_SignFailure *) buf; 556 557 ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec); 558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 559 "Signing failed!\n"); 560 finished = true; 561 break; 562 } 563 case TALER_HELPER_RSA_MT_AVAIL: 564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 565 "Received new key!\n"); 566 if (GNUNET_OK != 567 handle_mt_avail (dh, 568 hdr)) 569 { 570 GNUNET_break_op (0); 571 do_disconnect (dh); 572 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 573 goto end; 574 } 575 break; /* while(1) loop ensures we recvfrom() again */ 576 case TALER_HELPER_RSA_MT_PURGE: 577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 578 "Received revocation!\n"); 579 if (GNUNET_OK != 580 handle_mt_purge (dh, 581 hdr)) 582 { 583 GNUNET_break_op (0); 584 do_disconnect (dh); 585 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 586 goto end; 587 } 588 break; /* while(1) loop ensures we recvfrom() again */ 589 case TALER_HELPER_RSA_SYNCED: 590 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 591 "Synchronized add odd time with RSA helper!\n"); 592 dh->synced = true; 593 break; 594 default: 595 GNUNET_break_op (0); 596 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 597 "Received unexpected message of type %u\n", 598 ntohs (hdr->type)); 599 do_disconnect (dh); 600 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 601 goto end; 602 } 603 memmove (buf, 604 &buf[msize], 605 off - msize); 606 off -= msize; 607 goto more; 608 } /* while(1) */ 609 end: 610 if (finished) 611 TALER_blinded_denom_sig_free (bs); 612 return ec; 613 } 614 } 615 616 617 enum TALER_ErrorCode 618 TALER_CRYPTO_helper_rsa_batch_sign ( 619 struct TALER_CRYPTO_RsaDenominationHelper *dh, 620 unsigned int rsrs_length, 621 const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length], 622 struct TALER_BlindedDenominationSignature bss[static rsrs_length]) 623 { 624 enum TALER_ErrorCode ec = TALER_EC_INVALID; 625 unsigned int rpos; 626 unsigned int rend; 627 unsigned int wpos; 628 629 memset (bss, 630 0, 631 sizeof (*bss) * rsrs_length); 632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 633 "Starting signature process\n"); 634 if (GNUNET_OK != 635 try_connect (dh)) 636 { 637 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 638 "Failed to connect to helper\n"); 639 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; 640 } 641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 642 "Requesting %u signatures\n", 643 rsrs_length); 644 rpos = 0; 645 rend = 0; 646 wpos = 0; 647 while (rpos < rsrs_length) 648 { 649 unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest); 650 651 while ( (rend < rsrs_length) && 652 (mlen 653 + sizeof (struct TALER_CRYPTO_SignRequest) 654 + rsrs[rend].msg_size < UINT16_MAX) ) 655 { 656 mlen += sizeof (struct TALER_CRYPTO_SignRequest) + rsrs[rend].msg_size; 657 rend++; 658 } 659 { 660 char obuf[mlen] GNUNET_ALIGN; 661 struct TALER_CRYPTO_BatchSignRequest *bsr 662 = (struct TALER_CRYPTO_BatchSignRequest *) obuf; 663 void *wbuf; 664 665 bsr->header.type = htons (TALER_HELPER_RSA_MT_REQ_BATCH_SIGN); 666 bsr->header.size = htons (mlen); 667 bsr->batch_size = htonl (rend - rpos); 668 wbuf = &bsr[1]; 669 for (unsigned int i = rpos; i<rend; i++) 670 { 671 struct TALER_CRYPTO_SignRequest *sr = wbuf; 672 const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i]; 673 674 sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN); 675 sr->header.size = htons (sizeof (*sr) + rsr->msg_size); 676 sr->reserved = htonl (0); 677 sr->h_rsa = *rsr->h_rsa; 678 GNUNET_memcpy (&sr[1], 679 rsr->msg, 680 rsr->msg_size); 681 wbuf += sizeof (*sr) + rsr->msg_size; 682 } 683 GNUNET_assert (wbuf == &obuf[mlen]); 684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 685 "Sending batch request [%u-%u)\n", 686 rpos, 687 rend); 688 if (GNUNET_OK != 689 TALER_crypto_helper_send_all (dh->sock, 690 obuf, 691 sizeof (obuf))) 692 { 693 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 694 "send"); 695 do_disconnect (dh); 696 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; 697 } 698 } 699 rpos = rend; 700 { 701 char buf[UINT16_MAX]; 702 size_t off = 0; 703 const struct GNUNET_MessageHeader *hdr 704 = (const struct GNUNET_MessageHeader *) buf; 705 bool finished = false; 706 707 while (1) 708 { 709 uint16_t msize; 710 ssize_t ret; 711 712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 713 "Awaiting reply at %u (up to %u)\n", 714 wpos, 715 rend); 716 ret = recv (dh->sock, 717 &buf[off], 718 sizeof (buf) - off, 719 (finished && (0 == off)) 720 ? MSG_DONTWAIT 721 : 0); 722 if (ret < 0) 723 { 724 if (EINTR == errno) 725 continue; 726 if (EAGAIN == errno) 727 { 728 GNUNET_assert (finished); 729 GNUNET_assert (0 == off); 730 break; 731 } 732 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 733 "recv"); 734 do_disconnect (dh); 735 ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; 736 break; 737 } 738 if (0 == ret) 739 { 740 GNUNET_break (0 == off); 741 if (! finished) 742 ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG; 743 if (TALER_EC_NONE == ec) 744 break; 745 return ec; 746 } 747 off += ret; 748 more: 749 if (off < sizeof (struct GNUNET_MessageHeader)) 750 continue; 751 msize = ntohs (hdr->size); 752 if (off < msize) 753 continue; 754 switch (ntohs (hdr->type)) 755 { 756 case TALER_HELPER_RSA_MT_RES_SIGNATURE: 757 if (msize < sizeof (struct TALER_CRYPTO_SignResponse)) 758 { 759 GNUNET_break_op (0); 760 do_disconnect (dh); 761 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 762 } 763 if (finished) 764 { 765 GNUNET_break_op (0); 766 do_disconnect (dh); 767 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 768 } 769 { 770 const struct TALER_CRYPTO_SignResponse *sr = 771 (const struct TALER_CRYPTO_SignResponse *) buf; 772 struct GNUNET_CRYPTO_RsaSignature *rsa_signature; 773 struct GNUNET_CRYPTO_BlindedSignature *blind_sig; 774 775 rsa_signature = GNUNET_CRYPTO_rsa_signature_decode ( 776 &sr[1], 777 msize - sizeof (*sr)); 778 if (NULL == rsa_signature) 779 { 780 GNUNET_break_op (0); 781 do_disconnect (dh); 782 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 783 } 784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 785 "Received %u signature\n", 786 wpos); 787 blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); 788 blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA; 789 blind_sig->rc = 1; 790 blind_sig->details.blinded_rsa_signature = rsa_signature; 791 bss[wpos].blinded_sig = blind_sig; 792 wpos++; 793 if (wpos == rend) 794 { 795 if (TALER_EC_INVALID == ec) 796 ec = TALER_EC_NONE; 797 finished = true; 798 } 799 break; 800 } 801 case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE: 802 if (msize != sizeof (struct TALER_CRYPTO_SignFailure)) 803 { 804 GNUNET_break_op (0); 805 do_disconnect (dh); 806 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 807 } 808 { 809 const struct TALER_CRYPTO_SignFailure *sf = 810 (const struct TALER_CRYPTO_SignFailure *) buf; 811 812 ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec); 813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 814 "Signing %u failed with status %d!\n", 815 wpos, 816 ec); 817 wpos++; 818 if (wpos == rend) 819 { 820 finished = true; 821 } 822 break; 823 } 824 case TALER_HELPER_RSA_MT_AVAIL: 825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 826 "Received new key!\n"); 827 if (GNUNET_OK != 828 handle_mt_avail (dh, 829 hdr)) 830 { 831 GNUNET_break_op (0); 832 do_disconnect (dh); 833 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 834 } 835 break; /* while(1) loop ensures we recvfrom() again */ 836 case TALER_HELPER_RSA_MT_PURGE: 837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 838 "Received revocation!\n"); 839 if (GNUNET_OK != 840 handle_mt_purge (dh, 841 hdr)) 842 { 843 GNUNET_break_op (0); 844 do_disconnect (dh); 845 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 846 } 847 break; /* while(1) loop ensures we recvfrom() again */ 848 case TALER_HELPER_RSA_SYNCED: 849 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 850 "Synchronized add odd time with RSA helper!\n"); 851 dh->synced = true; 852 break; 853 default: 854 GNUNET_break_op (0); 855 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 856 "Received unexpected message of type %u\n", 857 ntohs (hdr->type)); 858 do_disconnect (dh); 859 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; 860 } 861 memmove (buf, 862 &buf[msize], 863 off - msize); 864 off -= msize; 865 goto more; 866 } /* while(1) */ 867 } /* scope */ 868 } /* while (rpos < rsrs_length) */ 869 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 870 "Existing with %u signatures and status %d\n", 871 wpos, 872 ec); 873 return ec; 874 } 875 876 877 void 878 TALER_CRYPTO_helper_rsa_revoke ( 879 struct TALER_CRYPTO_RsaDenominationHelper *dh, 880 const struct TALER_RsaPubHashP *h_rsa) 881 { 882 struct TALER_CRYPTO_RevokeRequest rr = { 883 .header.size = htons (sizeof (rr)), 884 .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE), 885 .h_rsa = *h_rsa 886 }; 887 888 if (GNUNET_OK != 889 try_connect (dh)) 890 return; /* give up */ 891 if (GNUNET_OK != 892 TALER_crypto_helper_send_all (dh->sock, 893 &rr, 894 sizeof (rr))) 895 { 896 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 897 "send"); 898 do_disconnect (dh); 899 return; 900 } 901 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 902 "Requested revocation of denomination key %s\n", 903 GNUNET_h2s (&h_rsa->hash)); 904 } 905 906 907 void 908 TALER_CRYPTO_helper_rsa_disconnect ( 909 struct TALER_CRYPTO_RsaDenominationHelper *dh) 910 { 911 if (-1 != dh->sock) 912 do_disconnect (dh); 913 GNUNET_free (dh); 914 } 915 916 917 /* end of crypto_helper_denom.c */