Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020, 2021, 2022 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_cs.c
18 : * @brief utility functions for running out-of-process private key operations
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "taler_util.h"
23 : #include "taler_signatures.h"
24 : #include "secmod_cs.h"
25 : #include <poll.h>
26 : #include "crypto_helper_common.h"
27 :
28 :
29 : struct TALER_CRYPTO_CsDenominationHelper
30 : {
31 : /**
32 : * Function to call with updates to available key material.
33 : */
34 : TALER_CRYPTO_CsDenominationKeyStatusCallback 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 38 : do_disconnect (struct TALER_CRYPTO_CsDenominationHelper *dh)
67 : {
68 38 : GNUNET_break (0 == close (dh->sock));
69 38 : dh->sock = -1;
70 38 : dh->synced = false;
71 38 : }
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 2062 : try_connect (struct TALER_CRYPTO_CsDenominationHelper *dh)
83 : {
84 2062 : if (-1 != dh->sock)
85 2024 : return GNUNET_OK;
86 38 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
87 : "Establishing connection!\n");
88 38 : dh->sock = socket (AF_UNIX,
89 : SOCK_STREAM,
90 : 0);
91 38 : if (-1 == dh->sock)
92 : {
93 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
94 : "socket");
95 0 : return GNUNET_SYSERR;
96 : }
97 38 : if (0 !=
98 38 : connect (dh->sock,
99 38 : (const struct sockaddr *) &dh->sa,
100 : sizeof (dh->sa)))
101 : {
102 0 : GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
103 : "connect",
104 : dh->sa.sun_path);
105 0 : do_disconnect (dh);
106 0 : return GNUNET_SYSERR;
107 : }
108 38 : TALER_CRYPTO_helper_cs_poll (dh);
109 38 : return GNUNET_OK;
110 : }
111 :
112 :
113 : struct TALER_CRYPTO_CsDenominationHelper *
114 38 : TALER_CRYPTO_helper_cs_connect (
115 : const struct GNUNET_CONFIGURATION_Handle *cfg,
116 : const char *section,
117 : TALER_CRYPTO_CsDenominationKeyStatusCallback dkc,
118 : void *dkc_cls)
119 : {
120 : struct TALER_CRYPTO_CsDenominationHelper *dh;
121 : char *unixpath;
122 : char *secname;
123 :
124 38 : GNUNET_asprintf (&secname,
125 : "%s-secmod-cs",
126 : section);
127 38 : if (GNUNET_OK !=
128 38 : GNUNET_CONFIGURATION_get_value_filename (cfg,
129 : secname,
130 : "UNIXPATH",
131 : &unixpath))
132 : {
133 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
134 : secname,
135 : "UNIXPATH");
136 0 : GNUNET_free (secname);
137 0 : return NULL;
138 : }
139 : /* we use >= here because we want the sun_path to always
140 : be 0-terminated */
141 38 : if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
142 : {
143 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
144 : secname,
145 : "UNIXPATH",
146 : "path too long");
147 0 : GNUNET_free (unixpath);
148 0 : GNUNET_free (secname);
149 0 : return NULL;
150 : }
151 38 : GNUNET_free (secname);
152 38 : dh = GNUNET_new (struct TALER_CRYPTO_CsDenominationHelper);
153 38 : dh->dkc = dkc;
154 38 : dh->dkc_cls = dkc_cls;
155 38 : dh->sa.sun_family = AF_UNIX;
156 38 : strncpy (dh->sa.sun_path,
157 : unixpath,
158 : sizeof (dh->sa.sun_path) - 1);
159 38 : GNUNET_free (unixpath);
160 38 : dh->sock = -1;
161 38 : if (GNUNET_OK !=
162 38 : try_connect (dh))
163 : {
164 0 : TALER_CRYPTO_helper_cs_disconnect (dh);
165 0 : return NULL;
166 : }
167 38 : return dh;
168 : }
169 :
170 :
171 : /**
172 : * Handle a #TALER_HELPER_CS_MT_AVAIL message from the helper.
173 : *
174 : * @param dh helper context
175 : * @param hdr message that we received
176 : * @return #GNUNET_OK on success
177 : */
178 : static enum GNUNET_GenericReturnValue
179 2744 : handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
180 : const struct GNUNET_MessageHeader *hdr)
181 : {
182 2744 : const struct TALER_CRYPTO_CsKeyAvailableNotification *kan
183 : = (const struct TALER_CRYPTO_CsKeyAvailableNotification *) hdr;
184 2744 : const char *buf = (const char *) &kan[1];
185 : const char *section_name;
186 : uint16_t snl;
187 :
188 2744 : if (sizeof (*kan) > ntohs (hdr->size))
189 : {
190 0 : GNUNET_break_op (0);
191 0 : return GNUNET_SYSERR;
192 : }
193 2744 : snl = ntohs (kan->section_name_len);
194 2744 : if (ntohs (hdr->size) != sizeof (*kan) + snl)
195 : {
196 0 : GNUNET_break_op (0);
197 0 : return GNUNET_SYSERR;
198 : }
199 2744 : if (0 == snl)
200 : {
201 0 : GNUNET_break_op (0);
202 0 : return GNUNET_SYSERR;
203 : }
204 2744 : section_name = buf;
205 2744 : if ('\0' != section_name[snl - 1])
206 : {
207 0 : GNUNET_break_op (0);
208 0 : return GNUNET_SYSERR;
209 : }
210 :
211 : {
212 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
213 : struct TALER_CsPubHashP h_cs;
214 :
215 2744 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
216 2744 : bsign_pub->cipher = GNUNET_CRYPTO_BSA_CS;
217 2744 : bsign_pub->rc = 1;
218 2744 : bsign_pub->details.cs_public_key = kan->denom_pub;
219 :
220 2744 : GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
221 : sizeof (bsign_pub->details.cs_public_key),
222 : &bsign_pub->pub_key_hash);
223 2744 : h_cs.hash = bsign_pub->pub_key_hash;
224 2744 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225 : "Received CS key %s (%s)\n",
226 : GNUNET_h2s (&h_cs.hash),
227 : section_name);
228 2744 : if (GNUNET_OK !=
229 2744 : TALER_exchange_secmod_cs_verify (
230 : &h_cs,
231 : section_name,
232 : GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
233 : GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
234 : &kan->secm_pub,
235 : &kan->secm_sig))
236 : {
237 0 : GNUNET_break_op (0);
238 0 : GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
239 0 : return GNUNET_SYSERR;
240 : }
241 2744 : dh->dkc (dh->dkc_cls,
242 : section_name,
243 : GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
244 : GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
245 : &h_cs,
246 : bsign_pub,
247 : &kan->secm_pub,
248 : &kan->secm_sig);
249 2744 : GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
250 : }
251 2744 : return GNUNET_OK;
252 : }
253 :
254 :
255 : /**
256 : * Handle a #TALER_HELPER_CS_MT_PURGE message from the helper.
257 : *
258 : * @param dh helper context
259 : * @param hdr message that we received
260 : * @return #GNUNET_OK on success
261 : */
262 : static enum GNUNET_GenericReturnValue
263 3 : handle_mt_purge (struct TALER_CRYPTO_CsDenominationHelper *dh,
264 : const struct GNUNET_MessageHeader *hdr)
265 : {
266 3 : const struct TALER_CRYPTO_CsKeyPurgeNotification *pn
267 : = (const struct TALER_CRYPTO_CsKeyPurgeNotification *) hdr;
268 :
269 3 : if (sizeof (*pn) != ntohs (hdr->size))
270 : {
271 0 : GNUNET_break_op (0);
272 0 : return GNUNET_SYSERR;
273 : }
274 3 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
275 : "Received revocation of denomination key %s\n",
276 : GNUNET_h2s (&pn->h_cs.hash));
277 3 : dh->dkc (dh->dkc_cls,
278 : NULL,
279 3 : GNUNET_TIME_UNIT_ZERO_TS,
280 3 : GNUNET_TIME_UNIT_ZERO,
281 : &pn->h_cs,
282 : NULL,
283 : NULL,
284 : NULL);
285 3 : return GNUNET_OK;
286 : }
287 :
288 :
289 : void
290 905 : TALER_CRYPTO_helper_cs_poll (struct TALER_CRYPTO_CsDenominationHelper *dh)
291 : {
292 : char buf[UINT16_MAX];
293 905 : size_t off = 0;
294 905 : unsigned int retry_limit = 3;
295 905 : const struct GNUNET_MessageHeader *hdr
296 : = (const struct GNUNET_MessageHeader *) buf;
297 :
298 905 : if (GNUNET_OK !=
299 905 : try_connect (dh))
300 0 : return; /* give up */
301 : while (1)
302 49 : {
303 : uint16_t msize;
304 : ssize_t ret;
305 :
306 954 : ret = recv (dh->sock,
307 : buf + off,
308 : sizeof (buf) - off,
309 954 : (dh->synced && (0 == off))
310 : ? MSG_DONTWAIT
311 : : 0);
312 954 : if (ret < 0)
313 : {
314 905 : if (EINTR == errno)
315 0 : continue;
316 905 : if (EAGAIN == errno)
317 : {
318 905 : GNUNET_assert (dh->synced);
319 905 : GNUNET_assert (0 == off);
320 905 : break;
321 : }
322 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
323 : "recv");
324 0 : do_disconnect (dh);
325 0 : if (0 == retry_limit)
326 0 : return; /* give up */
327 0 : if (GNUNET_OK !=
328 0 : try_connect (dh))
329 0 : return; /* give up */
330 0 : retry_limit--;
331 0 : continue;
332 : }
333 49 : if (0 == ret)
334 : {
335 0 : GNUNET_break (0 == off);
336 0 : return;
337 : }
338 49 : off += ret;
339 2834 : more:
340 2834 : if (off < sizeof (struct GNUNET_MessageHeader))
341 44 : continue;
342 2790 : msize = ntohs (hdr->size);
343 2790 : if (off < msize)
344 5 : continue;
345 2785 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 : "Received message of type %u and length %u\n",
347 : (unsigned int) ntohs (hdr->type),
348 : (unsigned int) msize);
349 2785 : switch (ntohs (hdr->type))
350 : {
351 2744 : case TALER_HELPER_CS_MT_AVAIL:
352 2744 : if (GNUNET_OK !=
353 2744 : handle_mt_avail (dh,
354 : hdr))
355 : {
356 0 : GNUNET_break_op (0);
357 0 : do_disconnect (dh);
358 0 : return;
359 : }
360 2744 : break;
361 3 : case TALER_HELPER_CS_MT_PURGE:
362 3 : if (GNUNET_OK !=
363 3 : handle_mt_purge (dh,
364 : hdr))
365 : {
366 0 : GNUNET_break_op (0);
367 0 : do_disconnect (dh);
368 0 : return;
369 : }
370 3 : break;
371 38 : case TALER_HELPER_CS_SYNCED:
372 38 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
373 : "Now synchronized with CS helper\n");
374 38 : dh->synced = true;
375 38 : break;
376 0 : default:
377 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
378 : "Received unexpected message of type %d (len: %u)\n",
379 : (unsigned int) ntohs (hdr->type),
380 : (unsigned int) msize);
381 0 : GNUNET_break_op (0);
382 0 : do_disconnect (dh);
383 0 : return;
384 : }
385 2785 : memmove (buf,
386 2785 : &buf[msize],
387 : off - msize);
388 2785 : off -= msize;
389 2785 : goto more;
390 : }
391 : }
392 :
393 :
394 : enum TALER_ErrorCode
395 902 : TALER_CRYPTO_helper_cs_sign (
396 : struct TALER_CRYPTO_CsDenominationHelper *dh,
397 : const struct TALER_CRYPTO_CsSignRequest *req,
398 : bool for_melt,
399 : struct TALER_BlindedDenominationSignature *bs)
400 : {
401 902 : enum TALER_ErrorCode ec = TALER_EC_INVALID;
402 902 : const struct TALER_CsPubHashP *h_cs = req->h_cs;
403 :
404 902 : memset (bs,
405 : 0,
406 : sizeof (*bs));
407 902 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 : "Starting signature process\n");
409 902 : if (GNUNET_OK !=
410 902 : try_connect (dh))
411 : {
412 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
413 : "Failed to connect to helper\n");
414 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
415 : }
416 :
417 902 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
418 : "Requesting signature\n");
419 : {
420 : char buf[sizeof (struct TALER_CRYPTO_CsSignRequestMessage)];
421 902 : struct TALER_CRYPTO_CsSignRequestMessage *sr
422 : = (struct TALER_CRYPTO_CsSignRequestMessage *) buf;
423 :
424 902 : sr->header.size = htons (sizeof (buf));
425 902 : sr->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
426 902 : sr->for_melt = htonl (for_melt ? 1 : 0);
427 902 : sr->h_cs = *h_cs;
428 902 : sr->message = *req->blinded_planchet;
429 902 : if (GNUNET_OK !=
430 902 : TALER_crypto_helper_send_all (dh->sock,
431 : buf,
432 : sizeof (buf)))
433 : {
434 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
435 : "send");
436 0 : do_disconnect (dh);
437 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
438 : }
439 : }
440 :
441 902 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
442 : "Awaiting reply\n");
443 : {
444 : char buf[UINT16_MAX];
445 902 : size_t off = 0;
446 902 : const struct GNUNET_MessageHeader *hdr
447 : = (const struct GNUNET_MessageHeader *) buf;
448 902 : bool finished = false;
449 :
450 : while (1)
451 902 : {
452 : uint16_t msize;
453 : ssize_t ret;
454 :
455 2706 : ret = recv (dh->sock,
456 1804 : &buf[off],
457 : sizeof (buf) - off,
458 902 : (finished && (0 == off))
459 : ? MSG_DONTWAIT
460 : : 0);
461 1804 : if (ret < 0)
462 : {
463 902 : if (EINTR == errno)
464 0 : continue;
465 902 : if (EAGAIN == errno)
466 : {
467 902 : GNUNET_assert (finished);
468 902 : GNUNET_assert (0 == off);
469 902 : return ec;
470 : }
471 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
472 : "recv");
473 0 : do_disconnect (dh);
474 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
475 0 : break;
476 : }
477 902 : if (0 == ret)
478 : {
479 0 : GNUNET_break (0 == off);
480 0 : if (! finished)
481 0 : ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
482 0 : return ec;
483 : }
484 902 : off += ret;
485 1804 : more:
486 1804 : if (off < sizeof (struct GNUNET_MessageHeader))
487 902 : continue;
488 902 : msize = ntohs (hdr->size);
489 902 : if (off < msize)
490 0 : continue;
491 902 : switch (ntohs (hdr->type))
492 : {
493 901 : case TALER_HELPER_CS_MT_RES_SIGNATURE:
494 901 : if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
495 : {
496 0 : GNUNET_break_op (0);
497 0 : do_disconnect (dh);
498 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
499 0 : goto end;
500 : }
501 901 : if (finished)
502 : {
503 0 : GNUNET_break_op (0);
504 0 : do_disconnect (dh);
505 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
506 0 : goto end;
507 : }
508 : {
509 901 : const struct TALER_CRYPTO_SignResponse *sr =
510 : (const struct TALER_CRYPTO_SignResponse *) buf;
511 : struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
512 :
513 901 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
514 : "Received signature\n");
515 901 : ec = TALER_EC_NONE;
516 901 : finished = true;
517 901 : blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
518 901 : blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
519 901 : blinded_sig->rc = 1;
520 901 : blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
521 901 : blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
522 901 : bs->blinded_sig = blinded_sig;
523 901 : break;
524 : }
525 1 : case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
526 1 : if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
527 : {
528 0 : GNUNET_break_op (0);
529 0 : do_disconnect (dh);
530 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
531 0 : goto end;
532 : }
533 : {
534 1 : const struct TALER_CRYPTO_SignFailure *sf =
535 : (const struct TALER_CRYPTO_SignFailure *) buf;
536 :
537 1 : ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
538 1 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
539 : "Signing failed with status %d!\n",
540 : ec);
541 1 : finished = true;
542 1 : break;
543 : }
544 0 : case TALER_HELPER_CS_MT_AVAIL:
545 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
546 : "Received new key!\n");
547 0 : if (GNUNET_OK !=
548 0 : handle_mt_avail (dh,
549 : hdr))
550 : {
551 0 : GNUNET_break_op (0);
552 0 : do_disconnect (dh);
553 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
554 0 : goto end;
555 : }
556 0 : break; /* while(1) loop ensures we recvfrom() again */
557 0 : case TALER_HELPER_CS_MT_PURGE:
558 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
559 : "Received revocation!\n");
560 0 : if (GNUNET_OK !=
561 0 : handle_mt_purge (dh,
562 : hdr))
563 : {
564 0 : GNUNET_break_op (0);
565 0 : do_disconnect (dh);
566 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
567 0 : goto end;
568 : }
569 0 : break; /* while(1) loop ensures we recvfrom() again */
570 0 : case TALER_HELPER_CS_SYNCED:
571 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
572 : "Synchronized add odd time with CS helper!\n");
573 0 : dh->synced = true;
574 0 : break;
575 0 : default:
576 0 : GNUNET_break_op (0);
577 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
578 : "Received unexpected message of type %u\n",
579 : ntohs (hdr->type));
580 0 : do_disconnect (dh);
581 0 : ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
582 0 : goto end;
583 : }
584 902 : memmove (buf,
585 902 : &buf[msize],
586 : off - msize);
587 902 : off -= msize;
588 902 : goto more;
589 : } /* while(1) */
590 0 : end:
591 0 : if (finished)
592 0 : TALER_blinded_denom_sig_free (bs);
593 0 : return ec;
594 : }
595 : }
596 :
597 :
598 : void
599 3 : TALER_CRYPTO_helper_cs_revoke (
600 : struct TALER_CRYPTO_CsDenominationHelper *dh,
601 : const struct TALER_CsPubHashP *h_cs)
602 : {
603 3 : struct TALER_CRYPTO_CsRevokeRequest rr = {
604 3 : .header.size = htons (sizeof (rr)),
605 3 : .header.type = htons (TALER_HELPER_CS_MT_REQ_REVOKE),
606 : .h_cs = *h_cs
607 : };
608 :
609 3 : if (GNUNET_OK !=
610 3 : try_connect (dh))
611 0 : return; /* give up */
612 3 : if (GNUNET_OK !=
613 3 : TALER_crypto_helper_send_all (dh->sock,
614 : &rr,
615 : sizeof (rr)))
616 : {
617 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
618 : "send");
619 0 : do_disconnect (dh);
620 0 : return;
621 : }
622 3 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
623 : "Requested revocation of denomination key %s\n",
624 : GNUNET_h2s (&h_cs->hash));
625 : }
626 :
627 :
628 : enum TALER_ErrorCode
629 22 : TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
630 : const struct TALER_CRYPTO_CsDeriveRequest *cdr,
631 : bool for_melt,
632 : struct GNUNET_CRYPTO_CSPublicRPairP *crp)
633 : {
634 22 : enum TALER_ErrorCode ec = TALER_EC_INVALID;
635 22 : const struct TALER_CsPubHashP *h_cs = cdr->h_cs;
636 22 : const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdr->nonce;
637 :
638 22 : memset (crp,
639 : 0,
640 : sizeof (*crp));
641 22 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
642 : "Starting R derivation process\n");
643 22 : if (GNUNET_OK !=
644 22 : try_connect (dh))
645 : {
646 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
647 : "Failed to connect to helper\n");
648 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
649 : }
650 :
651 22 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652 : "Requesting R\n");
653 : {
654 22 : struct TALER_CRYPTO_CsRDeriveRequest rdr = {
655 22 : .header.size = htons (sizeof (rdr)),
656 22 : .header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE),
657 22 : .for_melt = htonl (for_melt ? 1 : 0),
658 : .h_cs = *h_cs,
659 : .nonce = *nonce
660 : };
661 :
662 22 : if (GNUNET_OK !=
663 22 : TALER_crypto_helper_send_all (dh->sock,
664 : &rdr,
665 : sizeof (rdr)))
666 : {
667 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
668 : "send");
669 0 : do_disconnect (dh);
670 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
671 : }
672 : }
673 :
674 22 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
675 : "Awaiting reply\n");
676 : {
677 : char buf[UINT16_MAX];
678 22 : size_t off = 0;
679 22 : const struct GNUNET_MessageHeader *hdr
680 : = (const struct GNUNET_MessageHeader *) buf;
681 22 : bool finished = false;
682 :
683 : while (1)
684 22 : {
685 : uint16_t msize;
686 : ssize_t ret;
687 :
688 66 : ret = recv (dh->sock,
689 44 : &buf[off],
690 : sizeof (buf) - off,
691 22 : (finished && (0 == off))
692 : ? MSG_DONTWAIT
693 : : 0);
694 44 : if (ret < 0)
695 : {
696 22 : if (EINTR == errno)
697 0 : continue;
698 22 : if (EAGAIN == errno)
699 : {
700 22 : GNUNET_assert (finished);
701 22 : GNUNET_assert (0 == off);
702 22 : return ec;
703 : }
704 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
705 : "recv");
706 0 : do_disconnect (dh);
707 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
708 : }
709 22 : if (0 == ret)
710 : {
711 0 : GNUNET_break (0 == off);
712 0 : if (! finished)
713 0 : return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
714 0 : return ec;
715 : }
716 22 : off += ret;
717 44 : more:
718 44 : if (off < sizeof (struct GNUNET_MessageHeader))
719 22 : continue;
720 22 : msize = ntohs (hdr->size);
721 22 : if (off < msize)
722 0 : continue;
723 22 : switch (ntohs (hdr->type))
724 : {
725 11 : case TALER_HELPER_CS_MT_RES_RDERIVE:
726 11 : if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
727 : {
728 0 : GNUNET_break_op (0);
729 0 : do_disconnect (dh);
730 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
731 : }
732 11 : if (finished)
733 : {
734 0 : GNUNET_break_op (0);
735 0 : do_disconnect (dh);
736 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
737 : }
738 : {
739 11 : const struct TALER_CRYPTO_RDeriveResponse *rdr =
740 : (const struct TALER_CRYPTO_RDeriveResponse *) buf;
741 :
742 11 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 : "Received R\n");
744 11 : finished = true;
745 11 : ec = TALER_EC_NONE;
746 11 : *crp = rdr->r_pub;
747 11 : break;
748 : }
749 11 : case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
750 11 : if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
751 : {
752 0 : GNUNET_break_op (0);
753 0 : do_disconnect (dh);
754 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
755 : }
756 : {
757 11 : const struct TALER_CRYPTO_RDeriveFailure *rdf =
758 : (const struct TALER_CRYPTO_RDeriveFailure *) buf;
759 :
760 11 : ec = (enum TALER_ErrorCode) (int) ntohl (rdf->ec);
761 11 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 : "R derivation failed!\n");
763 11 : finished = true;
764 11 : break;
765 : }
766 0 : case TALER_HELPER_CS_MT_AVAIL:
767 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768 : "Received new key!\n");
769 0 : if (GNUNET_OK !=
770 0 : handle_mt_avail (dh,
771 : hdr))
772 : {
773 0 : GNUNET_break_op (0);
774 0 : do_disconnect (dh);
775 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
776 : }
777 0 : break; /* while(1) loop ensures we recvfrom() again */
778 0 : case TALER_HELPER_CS_MT_PURGE:
779 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
780 : "Received revocation!\n");
781 0 : if (GNUNET_OK !=
782 0 : handle_mt_purge (dh,
783 : hdr))
784 : {
785 0 : GNUNET_break_op (0);
786 0 : do_disconnect (dh);
787 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
788 : }
789 0 : break; /* while(1) loop ensures we recvfrom() again */
790 0 : case TALER_HELPER_CS_SYNCED:
791 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
792 : "Synchronized add odd time with CS helper!\n");
793 0 : dh->synced = true;
794 0 : break;
795 0 : default:
796 0 : GNUNET_break_op (0);
797 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 : "Received unexpected message of type %u\n",
799 : ntohs (hdr->type));
800 0 : do_disconnect (dh);
801 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
802 : }
803 22 : memmove (buf,
804 22 : &buf[msize],
805 : off - msize);
806 22 : off -= msize;
807 22 : goto more;
808 : } /* while(1) */
809 : }
810 : }
811 :
812 :
813 : enum TALER_ErrorCode
814 57 : TALER_CRYPTO_helper_cs_batch_sign (
815 : struct TALER_CRYPTO_CsDenominationHelper *dh,
816 : unsigned int reqs_length,
817 : const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
818 : bool for_melt,
819 : struct TALER_BlindedDenominationSignature bss[static reqs_length])
820 57 : {
821 57 : enum TALER_ErrorCode ec = TALER_EC_INVALID;
822 : unsigned int rpos;
823 : unsigned int rend;
824 : unsigned int wpos;
825 :
826 57 : memset (bss,
827 : 0,
828 : sizeof (*bss) * reqs_length);
829 57 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
830 : "Starting signature process\n");
831 57 : if (GNUNET_OK !=
832 57 : try_connect (dh))
833 : {
834 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
835 : "Failed to connect to helper\n");
836 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
837 : }
838 :
839 57 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
840 : "Requesting %u signatures\n",
841 : reqs_length);
842 57 : rpos = 0;
843 57 : rend = 0;
844 57 : wpos = 0;
845 114 : while (rpos < reqs_length)
846 : {
847 57 : unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
848 :
849 307 : while ( (rend < reqs_length) &&
850 250 : (mlen + sizeof (struct TALER_CRYPTO_CsSignRequestMessage)
851 : < UINT16_MAX) )
852 : {
853 250 : mlen += sizeof (struct TALER_CRYPTO_CsSignRequestMessage);
854 250 : rend++;
855 : }
856 57 : {
857 57 : char obuf[mlen] GNUNET_ALIGN;
858 57 : struct TALER_CRYPTO_BatchSignRequest *bsr
859 : = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
860 : void *wbuf;
861 :
862 57 : bsr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_SIGN);
863 57 : bsr->header.size = htons (mlen);
864 57 : bsr->batch_size = htonl (rend - rpos);
865 57 : wbuf = &bsr[1];
866 307 : for (unsigned int i = rpos; i<rend; i++)
867 : {
868 250 : struct TALER_CRYPTO_CsSignRequestMessage *csm = wbuf;
869 250 : const struct TALER_CRYPTO_CsSignRequest *csr = &reqs[i];
870 :
871 250 : csm->header.size = htons (sizeof (*csm));
872 250 : csm->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
873 250 : csm->for_melt = htonl (for_melt ? 1 : 0);
874 250 : csm->h_cs = *csr->h_cs;
875 250 : csm->message = *csr->blinded_planchet;
876 250 : wbuf += sizeof (*csm);
877 : }
878 57 : GNUNET_assert (wbuf == &obuf[mlen]);
879 57 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 : "Sending batch request [%u-%u)\n",
881 : rpos,
882 : rend);
883 57 : if (GNUNET_OK !=
884 57 : TALER_crypto_helper_send_all (dh->sock,
885 : obuf,
886 57 : sizeof (obuf)))
887 : {
888 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
889 : "send");
890 0 : do_disconnect (dh);
891 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
892 : }
893 : } /* end of obuf scope */
894 57 : rpos = rend;
895 : {
896 : char buf[UINT16_MAX];
897 57 : size_t off = 0;
898 57 : const struct GNUNET_MessageHeader *hdr
899 : = (const struct GNUNET_MessageHeader *) buf;
900 57 : bool finished = false;
901 :
902 : while (1)
903 140 : {
904 : uint16_t msize;
905 : ssize_t ret;
906 :
907 197 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
908 : "Awaiting reply at %u (up to %u)\n",
909 : wpos,
910 : rend);
911 254 : ret = recv (dh->sock,
912 197 : &buf[off],
913 : sizeof (buf) - off,
914 57 : (finished && (0 == off))
915 : ? MSG_DONTWAIT
916 : : 0);
917 197 : if (ret < 0)
918 : {
919 57 : if (EINTR == errno)
920 0 : continue;
921 57 : if (EAGAIN == errno)
922 : {
923 57 : GNUNET_assert (finished);
924 57 : GNUNET_assert (0 == off);
925 57 : break;
926 : }
927 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
928 : "recv");
929 0 : do_disconnect (dh);
930 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
931 : }
932 140 : if (0 == ret)
933 : {
934 0 : GNUNET_break (0 == off);
935 0 : if (! finished)
936 0 : return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
937 0 : if (TALER_EC_NONE == ec)
938 0 : break;
939 0 : return ec;
940 : }
941 140 : off += ret;
942 390 : more:
943 390 : if (off < sizeof (struct GNUNET_MessageHeader))
944 140 : continue;
945 250 : msize = ntohs (hdr->size);
946 250 : if (off < msize)
947 0 : continue;
948 250 : switch (ntohs (hdr->type))
949 : {
950 248 : case TALER_HELPER_CS_MT_RES_SIGNATURE:
951 248 : if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
952 : {
953 0 : GNUNET_break_op (0);
954 0 : do_disconnect (dh);
955 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
956 : }
957 248 : if (finished)
958 : {
959 0 : GNUNET_break_op (0);
960 0 : do_disconnect (dh);
961 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
962 : }
963 : {
964 248 : const struct TALER_CRYPTO_SignResponse *sr =
965 : (const struct TALER_CRYPTO_SignResponse *) buf;
966 : struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
967 248 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
968 : "Received %u signature\n",
969 : wpos);
970 248 : blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
971 248 : blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
972 248 : blinded_sig->rc = 1;
973 248 : blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
974 248 : blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
975 :
976 248 : bss[wpos].blinded_sig = blinded_sig;
977 248 : wpos++;
978 248 : if (wpos == rend)
979 : {
980 55 : if (TALER_EC_INVALID == ec)
981 55 : ec = TALER_EC_NONE;
982 55 : finished = true;
983 : }
984 248 : break;
985 : }
986 :
987 2 : case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
988 2 : if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
989 : {
990 0 : GNUNET_break_op (0);
991 0 : do_disconnect (dh);
992 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
993 : }
994 : {
995 2 : const struct TALER_CRYPTO_SignFailure *sf =
996 : (const struct TALER_CRYPTO_SignFailure *) buf;
997 :
998 2 : ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
999 2 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1000 : "Signing %u failed with status %d!\n",
1001 : wpos,
1002 : ec);
1003 2 : wpos++;
1004 2 : if (wpos == rend)
1005 : {
1006 2 : finished = true;
1007 : }
1008 2 : break;
1009 : }
1010 0 : case TALER_HELPER_CS_MT_AVAIL:
1011 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1012 : "Received new key!\n");
1013 0 : if (GNUNET_OK !=
1014 0 : handle_mt_avail (dh,
1015 : hdr))
1016 : {
1017 0 : GNUNET_break_op (0);
1018 0 : do_disconnect (dh);
1019 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1020 : }
1021 0 : break; /* while(1) loop ensures we recvfrom() again */
1022 0 : case TALER_HELPER_CS_MT_PURGE:
1023 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1024 : "Received revocation!\n");
1025 0 : if (GNUNET_OK !=
1026 0 : handle_mt_purge (dh,
1027 : hdr))
1028 : {
1029 0 : GNUNET_break_op (0);
1030 0 : do_disconnect (dh);
1031 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1032 : }
1033 0 : break; /* while(1) loop ensures we recvfrom() again */
1034 0 : case TALER_HELPER_CS_SYNCED:
1035 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1036 : "Synchronized add odd time with CS helper!\n");
1037 0 : dh->synced = true;
1038 0 : break;
1039 0 : default:
1040 0 : GNUNET_break_op (0);
1041 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1042 : "Received unexpected message of type %u\n",
1043 : ntohs (hdr->type));
1044 0 : do_disconnect (dh);
1045 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1046 : }
1047 250 : memmove (buf,
1048 250 : &buf[msize],
1049 : off - msize);
1050 250 : off -= msize;
1051 250 : goto more;
1052 : } /* while(1) */
1053 : } /* scope */
1054 : } /* while (rpos < cdrs_length) */
1055 57 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1056 : "Existing with %u signatures and status %d\n",
1057 : wpos,
1058 : ec);
1059 57 : return ec;
1060 : }
1061 :
1062 :
1063 : enum TALER_ErrorCode
1064 135 : TALER_CRYPTO_helper_cs_r_batch_derive (
1065 : struct TALER_CRYPTO_CsDenominationHelper *dh,
1066 : unsigned int cdrs_length,
1067 : const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
1068 : bool for_melt,
1069 : struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
1070 135 : {
1071 135 : enum TALER_ErrorCode ec = TALER_EC_INVALID;
1072 : unsigned int rpos;
1073 : unsigned int rend;
1074 : unsigned int wpos;
1075 :
1076 135 : memset (crps,
1077 : 0,
1078 : sizeof (*crps) * cdrs_length);
1079 135 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080 : "Starting R derivation process\n");
1081 135 : if (GNUNET_OK !=
1082 135 : try_connect (dh))
1083 : {
1084 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1085 : "Failed to connect to helper\n");
1086 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
1087 : }
1088 :
1089 135 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1090 : "Requesting %u R pairs\n",
1091 : cdrs_length);
1092 135 : rpos = 0;
1093 135 : rend = 0;
1094 135 : wpos = 0;
1095 270 : while (rpos < cdrs_length)
1096 : {
1097 135 : unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchDeriveRequest);
1098 :
1099 1236 : while ( (rend < cdrs_length) &&
1100 1101 : (mlen + sizeof (struct TALER_CRYPTO_CsRDeriveRequest)
1101 : < UINT16_MAX) )
1102 : {
1103 1101 : mlen += sizeof (struct TALER_CRYPTO_CsRDeriveRequest);
1104 1101 : rend++;
1105 : }
1106 135 : {
1107 135 : char obuf[mlen] GNUNET_ALIGN;
1108 135 : struct TALER_CRYPTO_BatchDeriveRequest *bdr
1109 : = (struct TALER_CRYPTO_BatchDeriveRequest *) obuf;
1110 : void *wbuf;
1111 :
1112 135 : bdr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_RDERIVE);
1113 135 : bdr->header.size = htons (mlen);
1114 135 : bdr->batch_size = htonl (rend - rpos);
1115 135 : wbuf = &bdr[1];
1116 1236 : for (unsigned int i = rpos; i<rend; i++)
1117 : {
1118 1101 : struct TALER_CRYPTO_CsRDeriveRequest *rdr = wbuf;
1119 1101 : const struct TALER_CRYPTO_CsDeriveRequest *cdr = &cdrs[i];
1120 :
1121 1101 : rdr->header.size = htons (sizeof (*rdr));
1122 1101 : rdr->header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
1123 1101 : rdr->for_melt = htonl (for_melt ? 1 : 0);
1124 1101 : rdr->h_cs = *cdr->h_cs;
1125 1101 : rdr->nonce = *cdr->nonce;
1126 1101 : wbuf += sizeof (*rdr);
1127 : }
1128 135 : GNUNET_assert (wbuf == &obuf[mlen]);
1129 135 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1130 : "Sending batch request [%u-%u)\n",
1131 : rpos,
1132 : rend);
1133 135 : if (GNUNET_OK !=
1134 135 : TALER_crypto_helper_send_all (dh->sock,
1135 : obuf,
1136 135 : sizeof (obuf)))
1137 : {
1138 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1139 : "send");
1140 0 : do_disconnect (dh);
1141 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
1142 : }
1143 : } /* end of obuf scope */
1144 135 : rpos = rend;
1145 : {
1146 : char buf[UINT16_MAX];
1147 135 : size_t off = 0;
1148 135 : const struct GNUNET_MessageHeader *hdr
1149 : = (const struct GNUNET_MessageHeader *) buf;
1150 135 : bool finished = false;
1151 :
1152 : while (1)
1153 470 : {
1154 : uint16_t msize;
1155 : ssize_t ret;
1156 :
1157 605 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1158 : "Awaiting reply at %u (up to %u)\n",
1159 : wpos,
1160 : rend);
1161 740 : ret = recv (dh->sock,
1162 605 : &buf[off],
1163 : sizeof (buf) - off,
1164 135 : (finished && (0 == off))
1165 : ? MSG_DONTWAIT
1166 : : 0);
1167 605 : if (ret < 0)
1168 : {
1169 135 : if (EINTR == errno)
1170 0 : continue;
1171 135 : if (EAGAIN == errno)
1172 : {
1173 135 : GNUNET_assert (finished);
1174 135 : GNUNET_assert (0 == off);
1175 135 : break;
1176 : }
1177 0 : GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1178 : "recv");
1179 0 : do_disconnect (dh);
1180 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
1181 : }
1182 470 : if (0 == ret)
1183 : {
1184 0 : GNUNET_break (0 == off);
1185 0 : if (! finished)
1186 0 : return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
1187 0 : if (TALER_EC_NONE == ec)
1188 0 : break;
1189 0 : return ec;
1190 : }
1191 470 : off += ret;
1192 1571 : more:
1193 1571 : if (off < sizeof (struct GNUNET_MessageHeader))
1194 470 : continue;
1195 1101 : msize = ntohs (hdr->size);
1196 1101 : if (off < msize)
1197 0 : continue;
1198 1101 : switch (ntohs (hdr->type))
1199 : {
1200 346 : case TALER_HELPER_CS_MT_RES_RDERIVE:
1201 346 : if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
1202 : {
1203 0 : GNUNET_break_op (0);
1204 0 : do_disconnect (dh);
1205 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1206 : }
1207 346 : if (finished)
1208 : {
1209 0 : GNUNET_break_op (0);
1210 0 : do_disconnect (dh);
1211 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1212 : }
1213 : {
1214 346 : const struct TALER_CRYPTO_RDeriveResponse *rdr =
1215 : (const struct TALER_CRYPTO_RDeriveResponse *) buf;
1216 :
1217 346 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218 : "Received %u R pair\n",
1219 : wpos);
1220 346 : crps[wpos] = rdr->r_pub;
1221 346 : wpos++;
1222 346 : if (wpos == rend)
1223 : {
1224 105 : if (TALER_EC_INVALID == ec)
1225 105 : ec = TALER_EC_NONE;
1226 105 : finished = true;
1227 : }
1228 346 : break;
1229 : }
1230 755 : case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
1231 755 : if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
1232 : {
1233 0 : GNUNET_break_op (0);
1234 0 : do_disconnect (dh);
1235 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1236 : }
1237 : {
1238 755 : const struct TALER_CRYPTO_RDeriveFailure *rdf =
1239 : (const struct TALER_CRYPTO_RDeriveFailure *) buf;
1240 :
1241 755 : ec = (enum TALER_ErrorCode) (int) ntohl (rdf->ec);
1242 755 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1243 : "R derivation %u failed with status %d!\n",
1244 : wpos,
1245 : ec);
1246 755 : wpos++;
1247 755 : if (wpos == rend)
1248 : {
1249 30 : finished = true;
1250 : }
1251 755 : break;
1252 : }
1253 0 : case TALER_HELPER_CS_MT_AVAIL:
1254 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1255 : "Received new key!\n");
1256 0 : if (GNUNET_OK !=
1257 0 : handle_mt_avail (dh,
1258 : hdr))
1259 : {
1260 0 : GNUNET_break_op (0);
1261 0 : do_disconnect (dh);
1262 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1263 : }
1264 0 : break; /* while(1) loop ensures we recvfrom() again */
1265 0 : case TALER_HELPER_CS_MT_PURGE:
1266 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1267 : "Received revocation!\n");
1268 0 : if (GNUNET_OK !=
1269 0 : handle_mt_purge (dh,
1270 : hdr))
1271 : {
1272 0 : GNUNET_break_op (0);
1273 0 : do_disconnect (dh);
1274 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1275 : }
1276 0 : break; /* while(1) loop ensures we recvfrom() again */
1277 0 : case TALER_HELPER_CS_SYNCED:
1278 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1279 : "Synchronized add odd time with CS helper!\n");
1280 0 : dh->synced = true;
1281 0 : break;
1282 0 : default:
1283 0 : GNUNET_break_op (0);
1284 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1285 : "Received unexpected message of type %u\n",
1286 : ntohs (hdr->type));
1287 0 : do_disconnect (dh);
1288 0 : return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
1289 : }
1290 1101 : memmove (buf,
1291 1101 : &buf[msize],
1292 : off - msize);
1293 1101 : off -= msize;
1294 1101 : goto more;
1295 : } /* while(1) */
1296 : } /* scope */
1297 : } /* while (rpos < cdrs_length) */
1298 135 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1299 : "Existing with %u signatures and status %d\n",
1300 : wpos,
1301 : ec);
1302 135 : return ec;
1303 : }
1304 :
1305 :
1306 : void
1307 38 : TALER_CRYPTO_helper_cs_disconnect (
1308 : struct TALER_CRYPTO_CsDenominationHelper *dh)
1309 : {
1310 38 : if (-1 != dh->sock)
1311 38 : do_disconnect (dh);
1312 38 : GNUNET_free (dh);
1313 38 : }
1314 :
1315 :
1316 : /* end of crypto_helper_cs.c */
|