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