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