Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2023 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 pq/pq_result_helper.c
18 : * @brief functions to initialize parameter arrays
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include <gnunet/gnunet_util_lib.h>
23 : #include "pq_common.h"
24 : #include "taler_pq_lib.h"
25 :
26 :
27 : /**
28 : * Extract an amount from a tuple including the currency from a Postgres
29 : * database @a result at row @a row.
30 : *
31 : * @param cls closure; not used
32 : * @param result where to extract data from
33 : * @param row row to extract data from
34 : * @param fname name (or prefix) of the fields to extract from
35 : * @param[in,out] dst_size where to store size of result, may be NULL
36 : * @param[out] dst where to store the result
37 : * @return
38 : * #GNUNET_YES if all results could be extracted
39 : * #GNUNET_NO if at least one result was NULL
40 : * #GNUNET_SYSERR if a result was invalid (non-existing field)
41 : */
42 : static enum GNUNET_GenericReturnValue
43 39 : extract_amount_currency_tuple (void *cls,
44 : PGresult *result,
45 : int row,
46 : const char *fname,
47 : size_t *dst_size,
48 : void *dst)
49 : {
50 39 : struct TALER_Amount *r_amount = dst;
51 : int col;
52 :
53 : (void) cls;
54 39 : if (sizeof (struct TALER_Amount) != *dst_size)
55 : {
56 0 : GNUNET_break (0);
57 0 : return GNUNET_SYSERR;
58 : }
59 :
60 : /* Set return value to invalid in case we don't finish */
61 39 : memset (r_amount,
62 : 0,
63 : sizeof (struct TALER_Amount));
64 39 : col = PQfnumber (result,
65 : fname);
66 39 : if (col < 0)
67 : {
68 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
69 : "Field `%s' does not exist in result\n",
70 : fname);
71 0 : return GNUNET_SYSERR;
72 : }
73 39 : if (PQgetisnull (result,
74 : row,
75 : col))
76 : {
77 0 : return GNUNET_NO;
78 : }
79 :
80 : /* Parse the tuple */
81 : {
82 : struct TALER_PQ_AmountCurrencyP ap;
83 : const char *in;
84 : size_t size;
85 :
86 39 : size = PQgetlength (result,
87 : row,
88 : col);
89 39 : if ( (size >= sizeof (ap)) ||
90 : (size <= sizeof (ap) - TALER_CURRENCY_LEN) )
91 : {
92 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
93 : "Incorrect size of binary field `%s' (got %zu, expected (%zu-%zu))\n",
94 : fname,
95 : size,
96 : sizeof (ap) - TALER_CURRENCY_LEN,
97 : sizeof (ap));
98 0 : return GNUNET_SYSERR;
99 : }
100 :
101 39 : in = PQgetvalue (result,
102 : row,
103 : col);
104 39 : memset (&ap.c,
105 : 0,
106 : TALER_CURRENCY_LEN);
107 39 : memcpy (&ap,
108 : in,
109 : size);
110 39 : if (3 != ntohl (ap.cnt))
111 : {
112 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
113 : "Incorrect number of elements in tuple-field `%s'\n",
114 : fname);
115 0 : return GNUNET_SYSERR;
116 : }
117 : /* FIXME[oec]: OID-checks? */
118 :
119 39 : r_amount->value = GNUNET_ntohll (ap.v);
120 39 : r_amount->fraction = ntohl (ap.f);
121 39 : memcpy (r_amount->currency,
122 : ap.c,
123 : TALER_CURRENCY_LEN);
124 39 : if ('\0' != r_amount->currency[TALER_CURRENCY_LEN - 1])
125 : {
126 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 : "Invalid currency (not 0-terminated) in tuple field `%s'\n",
128 : fname);
129 : /* be sure nobody uses this by accident */
130 0 : memset (r_amount,
131 : 0,
132 : sizeof (struct TALER_Amount));
133 0 : return GNUNET_SYSERR;
134 : }
135 : }
136 :
137 39 : if (r_amount->value >= TALER_AMOUNT_MAX_VALUE)
138 : {
139 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
140 : "Value in field `%s' exceeds legal range\n",
141 : fname);
142 0 : return GNUNET_SYSERR;
143 : }
144 39 : if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE)
145 : {
146 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
147 : "Fraction in field `%s' exceeds legal range\n",
148 : fname);
149 0 : return GNUNET_SYSERR;
150 : }
151 39 : return GNUNET_OK;
152 : }
153 :
154 :
155 : struct GNUNET_PQ_ResultSpec
156 39 : TALER_PQ_result_spec_amount_with_currency (const char *name,
157 : struct TALER_Amount *amount)
158 : {
159 39 : struct GNUNET_PQ_ResultSpec res = {
160 : .conv = &extract_amount_currency_tuple,
161 : .dst = (void *) amount,
162 : .dst_size = sizeof (*amount),
163 : .fname = name
164 : };
165 :
166 39 : return res;
167 : }
168 :
169 :
170 : /**
171 : * Extract an amount from a tuple from a Postgres database @a result at row @a row.
172 : *
173 : * @param cls closure, a `const char *` giving the currency
174 : * @param result where to extract data from
175 : * @param row row to extract data from
176 : * @param fname name (or prefix) of the fields to extract from
177 : * @param[in,out] dst_size where to store size of result, may be NULL
178 : * @param[out] dst where to store the result
179 : * @return
180 : * #GNUNET_YES if all results could be extracted
181 : * #GNUNET_NO if at least one result was NULL
182 : * #GNUNET_SYSERR if a result was invalid (non-existing field)
183 : */
184 : static enum GNUNET_GenericReturnValue
185 415080 : extract_amount_tuple (void *cls,
186 : PGresult *result,
187 : int row,
188 : const char *fname,
189 : size_t *dst_size,
190 : void *dst)
191 : {
192 415080 : struct TALER_Amount *r_amount = dst;
193 415080 : const char *currency = cls;
194 : int col;
195 : size_t len;
196 :
197 415080 : if (sizeof (struct TALER_Amount) != *dst_size)
198 : {
199 0 : GNUNET_break (0);
200 0 : return GNUNET_SYSERR;
201 : }
202 :
203 : /* Set return value to invalid in case we don't finish */
204 415080 : memset (r_amount,
205 : 0,
206 : sizeof (struct TALER_Amount));
207 415080 : col = PQfnumber (result,
208 : fname);
209 415080 : if (col < 0)
210 : {
211 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
212 : "Field `%s' does not exist in result\n",
213 : fname);
214 0 : return GNUNET_SYSERR;
215 : }
216 415080 : if (PQgetisnull (result,
217 : row,
218 : col))
219 : {
220 0 : return GNUNET_NO;
221 : }
222 :
223 : /* Parse the tuple */
224 : {
225 : struct TALER_PQ_AmountP ap;
226 : const char *in;
227 : size_t size;
228 :
229 415080 : size = PQgetlength (result,
230 : row,
231 : col);
232 415080 : in = PQgetvalue (result,
233 : row,
234 : col);
235 415080 : if (sizeof(struct TALER_PQ_AmountNullP) == size)
236 : {
237 : struct TALER_PQ_AmountNullP apn;
238 :
239 2425 : memcpy (&apn,
240 : in,
241 : size);
242 2425 : if ( (2 == ntohl (apn.cnt)) &&
243 2425 : (-1 == (int32_t) ntohl (apn.sz_v)) &&
244 2425 : (-1 == (int32_t) ntohl (apn.sz_f)) )
245 : {
246 : /* is NULL! */
247 2425 : return GNUNET_NO;
248 : }
249 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
250 : "Incorrect size of binary field `%s' and not NULL (got %zu, expected %zu)\n",
251 : fname,
252 : size,
253 : sizeof(ap));
254 0 : return GNUNET_SYSERR;
255 : }
256 412655 : if (sizeof(ap) != size)
257 : {
258 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
259 : "Incorrect size of binary field `%s' (got %zu, expected %zu)\n",
260 : fname,
261 : size,
262 : sizeof(ap));
263 0 : return GNUNET_SYSERR;
264 : }
265 :
266 412655 : memcpy (&ap,
267 : in,
268 : size);
269 412655 : if (2 != ntohl (ap.cnt))
270 : {
271 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
272 : "Incorrect number of elements in tuple-field `%s'\n",
273 : fname);
274 0 : return GNUNET_SYSERR;
275 : }
276 : /* FIXME[oec]: OID-checks? */
277 :
278 412655 : r_amount->value = GNUNET_ntohll (ap.v);
279 412655 : r_amount->fraction = ntohl (ap.f);
280 : }
281 :
282 412655 : if (r_amount->value >= TALER_AMOUNT_MAX_VALUE)
283 : {
284 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
285 : "Value in field `%s' exceeds legal range\n",
286 : fname);
287 0 : return GNUNET_SYSERR;
288 : }
289 412655 : if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE)
290 : {
291 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
292 : "Fraction in field `%s' exceeds legal range\n",
293 : fname);
294 0 : return GNUNET_SYSERR;
295 : }
296 :
297 412655 : len = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
298 : strlen (currency));
299 :
300 412655 : GNUNET_memcpy (r_amount->currency,
301 : currency,
302 : len);
303 412655 : return GNUNET_OK;
304 : }
305 :
306 :
307 : struct GNUNET_PQ_ResultSpec
308 447971 : TALER_PQ_result_spec_amount (const char *name,
309 : const char *currency,
310 : struct TALER_Amount *amount)
311 : {
312 447971 : struct GNUNET_PQ_ResultSpec res = {
313 : .conv = &extract_amount_tuple,
314 : .cls = (void *) currency,
315 : .dst = (void *) amount,
316 : .dst_size = sizeof (*amount),
317 : .fname = name
318 : };
319 :
320 447971 : return res;
321 : }
322 :
323 :
324 : /**
325 : * Extract data from a Postgres database @a result at row @a row.
326 : *
327 : * @param cls closure
328 : * @param result where to extract data from
329 : * @param row row to extract data from
330 : * @param fname name (or prefix) of the fields to extract from
331 : * @param[in,out] dst_size where to store size of result, may be NULL
332 : * @param[out] dst where to store the result
333 : * @return
334 : * #GNUNET_YES if all results could be extracted
335 : * #GNUNET_NO if at least one result was NULL
336 : * #GNUNET_SYSERR if a result was invalid (non-existing field)
337 : */
338 : static enum GNUNET_GenericReturnValue
339 292 : extract_json (void *cls,
340 : PGresult *result,
341 : int row,
342 : const char *fname,
343 : size_t *dst_size,
344 : void *dst)
345 : {
346 292 : json_t **j_dst = dst;
347 : const char *res;
348 : int fnum;
349 : json_error_t json_error;
350 : size_t slen;
351 :
352 : (void) cls;
353 : (void) dst_size;
354 292 : fnum = PQfnumber (result,
355 : fname);
356 292 : if (fnum < 0)
357 : {
358 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
359 : "Field `%s' does not exist in result\n",
360 : fname);
361 0 : return GNUNET_SYSERR;
362 : }
363 292 : if (PQgetisnull (result,
364 : row,
365 : fnum))
366 120 : return GNUNET_NO;
367 172 : slen = PQgetlength (result,
368 : row,
369 : fnum);
370 172 : res = (const char *) PQgetvalue (result,
371 : row,
372 : fnum);
373 172 : *j_dst = json_loadb (res,
374 : slen,
375 : JSON_REJECT_DUPLICATES,
376 : &json_error);
377 172 : if (NULL == *j_dst)
378 : {
379 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
380 : "Failed to parse JSON result for field `%s': %s (%s)\n",
381 : fname,
382 : json_error.text,
383 : json_error.source);
384 0 : return GNUNET_SYSERR;
385 : }
386 172 : return GNUNET_OK;
387 : }
388 :
389 :
390 : /**
391 : * Function called to clean up memory allocated
392 : * by a #GNUNET_PQ_ResultConverter.
393 : *
394 : * @param cls closure
395 : * @param rd result data to clean up
396 : */
397 : static void
398 67 : clean_json (void *cls,
399 : void *rd)
400 : {
401 67 : json_t **dst = rd;
402 :
403 : (void) cls;
404 67 : if (NULL != *dst)
405 : {
406 62 : json_decref (*dst);
407 62 : *dst = NULL;
408 : }
409 67 : }
410 :
411 :
412 : struct GNUNET_PQ_ResultSpec
413 364 : TALER_PQ_result_spec_json (const char *name,
414 : json_t **jp)
415 : {
416 364 : struct GNUNET_PQ_ResultSpec res = {
417 : .conv = &extract_json,
418 : .cleaner = &clean_json,
419 : .dst = (void *) jp,
420 : .fname = name
421 : };
422 :
423 364 : return res;
424 : }
425 :
426 :
427 : /**
428 : * Extract data from a Postgres database @a result at row @a row.
429 : *
430 : * @param cls closure
431 : * @param result where to extract data from
432 : * @param row the row to extract data from
433 : * @param fname name (or prefix) of the fields to extract from
434 : * @param[in,out] dst_size where to store size of result, may be NULL
435 : * @param[out] dst where to store the result
436 : * @return
437 : * #GNUNET_YES if all results could be extracted
438 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
439 : */
440 : static enum GNUNET_GenericReturnValue
441 77792 : extract_denom_pub (void *cls,
442 : PGresult *result,
443 : int row,
444 : const char *fname,
445 : size_t *dst_size,
446 : void *dst)
447 : {
448 77792 : struct TALER_DenominationPublicKey *pk = dst;
449 : struct GNUNET_CRYPTO_BlindSignPublicKey *bpk;
450 : size_t len;
451 : const char *res;
452 : int fnum;
453 : uint32_t be[2];
454 :
455 : (void) cls;
456 : (void) dst_size;
457 77792 : fnum = PQfnumber (result,
458 : fname);
459 77792 : if (fnum < 0)
460 : {
461 0 : GNUNET_break (0);
462 0 : return GNUNET_SYSERR;
463 : }
464 77792 : if (PQgetisnull (result,
465 : row,
466 : fnum))
467 0 : return GNUNET_NO;
468 :
469 : /* if a field is null, continue but
470 : * remember that we now return a different result */
471 77792 : len = PQgetlength (result,
472 : row,
473 : fnum);
474 77792 : res = PQgetvalue (result,
475 : row,
476 : fnum);
477 77792 : if (len < sizeof (be))
478 : {
479 0 : GNUNET_break (0);
480 0 : return GNUNET_SYSERR;
481 : }
482 77792 : GNUNET_memcpy (be,
483 : res,
484 : sizeof (be));
485 77792 : res += sizeof (be);
486 77792 : len -= sizeof (be);
487 77792 : bpk = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
488 77792 : bpk->cipher = ntohl (be[0]);
489 77792 : bpk->rc = 1;
490 77792 : pk->age_mask.bits = ntohl (be[1]);
491 77792 : switch (bpk->cipher)
492 : {
493 0 : case GNUNET_CRYPTO_BSA_INVALID:
494 0 : break;
495 72995 : case GNUNET_CRYPTO_BSA_RSA:
496 : bpk->details.rsa_public_key
497 72995 : = GNUNET_CRYPTO_rsa_public_key_decode (res,
498 : len);
499 72995 : if (NULL == bpk->details.rsa_public_key)
500 : {
501 0 : GNUNET_break (0);
502 0 : GNUNET_free (bpk);
503 0 : return GNUNET_SYSERR;
504 : }
505 72995 : pk->bsign_pub_key = bpk;
506 72995 : GNUNET_CRYPTO_hash (res,
507 : len,
508 : &bpk->pub_key_hash);
509 72995 : return GNUNET_OK;
510 4797 : case GNUNET_CRYPTO_BSA_CS:
511 4797 : if (sizeof (bpk->details.cs_public_key) != len)
512 : {
513 0 : GNUNET_break (0);
514 0 : GNUNET_free (bpk);
515 0 : return GNUNET_SYSERR;
516 : }
517 4797 : GNUNET_memcpy (&bpk->details.cs_public_key,
518 : res,
519 : len);
520 4797 : pk->bsign_pub_key = bpk;
521 4797 : GNUNET_CRYPTO_hash (res,
522 : len,
523 : &bpk->pub_key_hash);
524 4797 : return GNUNET_OK;
525 : }
526 0 : GNUNET_break (0);
527 0 : GNUNET_free (bpk);
528 0 : return GNUNET_SYSERR;
529 : }
530 :
531 :
532 : /**
533 : * Function called to clean up memory allocated
534 : * by a #GNUNET_PQ_ResultConverter.
535 : *
536 : * @param cls closure
537 : * @param rd result data to clean up
538 : */
539 : static void
540 11646 : clean_denom_pub (void *cls,
541 : void *rd)
542 : {
543 11646 : struct TALER_DenominationPublicKey *denom_pub = rd;
544 :
545 : (void) cls;
546 11646 : TALER_denom_pub_free (denom_pub);
547 11646 : }
548 :
549 :
550 : struct GNUNET_PQ_ResultSpec
551 77792 : TALER_PQ_result_spec_denom_pub (const char *name,
552 : struct TALER_DenominationPublicKey *denom_pub)
553 : {
554 77792 : struct GNUNET_PQ_ResultSpec res = {
555 : .conv = &extract_denom_pub,
556 : .cleaner = &clean_denom_pub,
557 : .dst = (void *) denom_pub,
558 : .fname = name
559 : };
560 :
561 77792 : return res;
562 : }
563 :
564 :
565 : /**
566 : * Extract data from a Postgres database @a result at row @a row.
567 : *
568 : * @param cls closure
569 : * @param result where to extract data from
570 : * @param row the row to extract data from
571 : * @param fname name (or prefix) of the fields to extract from
572 : * @param[in,out] dst_size where to store size of result, may be NULL
573 : * @param[out] dst where to store the result
574 : * @return
575 : * #GNUNET_YES if all results could be extracted
576 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
577 : */
578 : static enum GNUNET_GenericReturnValue
579 282 : extract_denom_sig (void *cls,
580 : PGresult *result,
581 : int row,
582 : const char *fname,
583 : size_t *dst_size,
584 : void *dst)
585 : {
586 282 : struct TALER_DenominationSignature *sig = dst;
587 : struct GNUNET_CRYPTO_UnblindedSignature *ubs;
588 : size_t len;
589 : const char *res;
590 : int fnum;
591 : uint32_t be[2];
592 :
593 : (void) cls;
594 : (void) dst_size;
595 282 : fnum = PQfnumber (result,
596 : fname);
597 282 : if (fnum < 0)
598 : {
599 0 : GNUNET_break (0);
600 0 : return GNUNET_SYSERR;
601 : }
602 282 : if (PQgetisnull (result,
603 : row,
604 : fnum))
605 0 : return GNUNET_NO;
606 :
607 : /* if a field is null, continue but
608 : * remember that we now return a different result */
609 282 : len = PQgetlength (result,
610 : row,
611 : fnum);
612 282 : res = PQgetvalue (result,
613 : row,
614 : fnum);
615 282 : if (len < sizeof (be))
616 : {
617 0 : GNUNET_break (0);
618 0 : return GNUNET_SYSERR;
619 : }
620 282 : GNUNET_memcpy (&be,
621 : res,
622 : sizeof (be));
623 282 : if (0x00 != ntohl (be[1]))
624 : {
625 0 : GNUNET_break (0);
626 0 : return GNUNET_SYSERR;
627 : }
628 282 : res += sizeof (be);
629 282 : len -= sizeof (be);
630 282 : ubs = GNUNET_new (struct GNUNET_CRYPTO_UnblindedSignature);
631 282 : ubs->rc = 1;
632 282 : ubs->cipher = ntohl (be[0]);
633 282 : switch (ubs->cipher)
634 : {
635 0 : case GNUNET_CRYPTO_BSA_INVALID:
636 0 : break;
637 282 : case GNUNET_CRYPTO_BSA_RSA:
638 : ubs->details.rsa_signature
639 282 : = GNUNET_CRYPTO_rsa_signature_decode (res,
640 : len);
641 282 : if (NULL == ubs->details.rsa_signature)
642 : {
643 0 : GNUNET_break (0);
644 0 : GNUNET_free (ubs);
645 0 : return GNUNET_SYSERR;
646 : }
647 282 : sig->unblinded_sig = ubs;
648 282 : return GNUNET_OK;
649 0 : case GNUNET_CRYPTO_BSA_CS:
650 0 : if (sizeof (ubs->details.cs_signature) != len)
651 : {
652 0 : GNUNET_break (0);
653 0 : GNUNET_free (ubs);
654 0 : return GNUNET_SYSERR;
655 : }
656 0 : GNUNET_memcpy (&ubs->details.cs_signature,
657 : res,
658 : len);
659 0 : sig->unblinded_sig = ubs;
660 0 : return GNUNET_OK;
661 : }
662 0 : GNUNET_break (0);
663 0 : GNUNET_free (ubs);
664 0 : return GNUNET_SYSERR;
665 : }
666 :
667 :
668 : /**
669 : * Function called to clean up memory allocated
670 : * by a #GNUNET_PQ_ResultConverter.
671 : *
672 : * @param cls closure
673 : * @param rd result data to clean up
674 : */
675 : static void
676 3 : clean_denom_sig (void *cls,
677 : void *rd)
678 : {
679 3 : struct TALER_DenominationSignature *denom_sig = rd;
680 :
681 : (void) cls;
682 3 : TALER_denom_sig_free (denom_sig);
683 3 : }
684 :
685 :
686 : struct GNUNET_PQ_ResultSpec
687 282 : TALER_PQ_result_spec_denom_sig (const char *name,
688 : struct TALER_DenominationSignature *denom_sig)
689 : {
690 282 : struct GNUNET_PQ_ResultSpec res = {
691 : .conv = &extract_denom_sig,
692 : .cleaner = &clean_denom_sig,
693 : .dst = (void *) denom_sig,
694 : .fname = name
695 : };
696 :
697 282 : return res;
698 : }
699 :
700 :
701 : /**
702 : * Extract data from a Postgres database @a result at row @a row.
703 : *
704 : * @param cls closure
705 : * @param result where to extract data from
706 : * @param row the row to extract data from
707 : * @param fname name (or prefix) of the fields to extract from
708 : * @param[in,out] dst_size where to store size of result, may be NULL
709 : * @param[out] dst where to store the result
710 : * @return
711 : * #GNUNET_YES if all results could be extracted
712 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
713 : */
714 : static enum GNUNET_GenericReturnValue
715 0 : extract_blinded_denom_sig (void *cls,
716 : PGresult *result,
717 : int row,
718 : const char *fname,
719 : size_t *dst_size,
720 : void *dst)
721 : {
722 0 : struct TALER_BlindedDenominationSignature *sig = dst;
723 : struct GNUNET_CRYPTO_BlindedSignature *bs;
724 : size_t len;
725 : const char *res;
726 : int fnum;
727 : uint32_t be[2];
728 :
729 : (void) cls;
730 : (void) dst_size;
731 0 : fnum = PQfnumber (result,
732 : fname);
733 0 : if (fnum < 0)
734 : {
735 0 : GNUNET_break (0);
736 0 : return GNUNET_SYSERR;
737 : }
738 0 : if (PQgetisnull (result,
739 : row,
740 : fnum))
741 0 : return GNUNET_NO;
742 :
743 : /* if a field is null, continue but
744 : * remember that we now return a different result */
745 0 : len = PQgetlength (result,
746 : row,
747 : fnum);
748 0 : res = PQgetvalue (result,
749 : row,
750 : fnum);
751 0 : if (len < sizeof (be))
752 : {
753 0 : GNUNET_break (0);
754 0 : return GNUNET_SYSERR;
755 : }
756 0 : GNUNET_memcpy (&be,
757 : res,
758 : sizeof (be));
759 0 : if (0x01 != ntohl (be[1])) /* magic marker: blinded */
760 : {
761 0 : GNUNET_break (0);
762 0 : return GNUNET_SYSERR;
763 : }
764 0 : res += sizeof (be);
765 0 : len -= sizeof (be);
766 0 : bs = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
767 0 : bs->rc = 1;
768 0 : bs->cipher = ntohl (be[0]);
769 0 : switch (bs->cipher)
770 : {
771 0 : case GNUNET_CRYPTO_BSA_INVALID:
772 0 : break;
773 0 : case GNUNET_CRYPTO_BSA_RSA:
774 : bs->details.blinded_rsa_signature
775 0 : = GNUNET_CRYPTO_rsa_signature_decode (res,
776 : len);
777 0 : if (NULL == bs->details.blinded_rsa_signature)
778 : {
779 0 : GNUNET_break (0);
780 0 : GNUNET_free (bs);
781 0 : return GNUNET_SYSERR;
782 : }
783 0 : sig->blinded_sig = bs;
784 0 : return GNUNET_OK;
785 0 : case GNUNET_CRYPTO_BSA_CS:
786 0 : if (sizeof (bs->details.blinded_cs_answer) != len)
787 : {
788 0 : GNUNET_break (0);
789 0 : GNUNET_free (bs);
790 0 : return GNUNET_SYSERR;
791 : }
792 0 : GNUNET_memcpy (&bs->details.blinded_cs_answer,
793 : res,
794 : len);
795 0 : sig->blinded_sig = bs;
796 0 : return GNUNET_OK;
797 : }
798 0 : GNUNET_break (0);
799 0 : GNUNET_free (bs);
800 0 : return GNUNET_SYSERR;
801 : }
802 :
803 :
804 : /**
805 : * Function called to clean up memory allocated
806 : * by a #GNUNET_PQ_ResultConverter.
807 : *
808 : * @param cls closure
809 : * @param rd result data to clean up
810 : */
811 : static void
812 0 : clean_blinded_denom_sig (void *cls,
813 : void *rd)
814 : {
815 0 : struct TALER_BlindedDenominationSignature *denom_sig = rd;
816 :
817 : (void) cls;
818 0 : TALER_blinded_denom_sig_free (denom_sig);
819 0 : }
820 :
821 :
822 : struct GNUNET_PQ_ResultSpec
823 0 : TALER_PQ_result_spec_blinded_denom_sig (
824 : const char *name,
825 : struct TALER_BlindedDenominationSignature *denom_sig)
826 : {
827 0 : struct GNUNET_PQ_ResultSpec res = {
828 : .conv = &extract_blinded_denom_sig,
829 : .cleaner = &clean_blinded_denom_sig,
830 : .dst = (void *) denom_sig,
831 : .fname = name
832 : };
833 :
834 0 : return res;
835 : }
836 :
837 :
838 : /**
839 : * Extract data from a Postgres database @a result at row @a row.
840 : *
841 : * @param cls closure
842 : * @param result where to extract data from
843 : * @param row the row to extract data from
844 : * @param fname name (or prefix) of the fields to extract from
845 : * @param[in,out] dst_size where to store size of result, may be NULL
846 : * @param[out] dst where to store the result
847 : * @return
848 : * #GNUNET_YES if all results could be extracted
849 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
850 : */
851 : static enum GNUNET_GenericReturnValue
852 0 : extract_blinded_planchet (void *cls,
853 : PGresult *result,
854 : int row,
855 : const char *fname,
856 : size_t *dst_size,
857 : void *dst)
858 : {
859 0 : struct TALER_BlindedPlanchet *bp = dst;
860 : struct GNUNET_CRYPTO_BlindedMessage *bm;
861 : size_t len;
862 : const char *res;
863 : int fnum;
864 : uint32_t be[2];
865 :
866 : (void) cls;
867 : (void) dst_size;
868 0 : fnum = PQfnumber (result,
869 : fname);
870 0 : if (fnum < 0)
871 : {
872 0 : GNUNET_break (0);
873 0 : return GNUNET_SYSERR;
874 : }
875 0 : if (PQgetisnull (result,
876 : row,
877 : fnum))
878 0 : return GNUNET_NO;
879 :
880 : /* if a field is null, continue but
881 : * remember that we now return a different result */
882 0 : len = PQgetlength (result,
883 : row,
884 : fnum);
885 0 : res = PQgetvalue (result,
886 : row,
887 : fnum);
888 0 : if (len < sizeof (be))
889 : {
890 0 : GNUNET_break (0);
891 0 : return GNUNET_SYSERR;
892 : }
893 0 : GNUNET_memcpy (&be,
894 : res,
895 : sizeof (be));
896 0 : if (0x0100 != ntohl (be[1])) /* magic marker: blinded */
897 : {
898 0 : GNUNET_break (0);
899 0 : return GNUNET_SYSERR;
900 : }
901 0 : res += sizeof (be);
902 0 : len -= sizeof (be);
903 0 : bm = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
904 0 : bm->rc = 1;
905 0 : bm->cipher = ntohl (be[0]);
906 0 : switch (bm->cipher)
907 : {
908 0 : case GNUNET_CRYPTO_BSA_INVALID:
909 0 : break;
910 0 : case GNUNET_CRYPTO_BSA_RSA:
911 : bm->details.rsa_blinded_message.blinded_msg_size
912 0 : = len;
913 : bm->details.rsa_blinded_message.blinded_msg
914 0 : = GNUNET_memdup (res,
915 : len);
916 0 : bp->blinded_message = bm;
917 0 : return GNUNET_OK;
918 0 : case GNUNET_CRYPTO_BSA_CS:
919 0 : if (sizeof (bm->details.cs_blinded_message) != len)
920 : {
921 0 : GNUNET_break (0);
922 0 : GNUNET_free (bm);
923 0 : return GNUNET_SYSERR;
924 : }
925 0 : GNUNET_memcpy (&bm->details.cs_blinded_message,
926 : res,
927 : len);
928 0 : bp->blinded_message = bm;
929 0 : return GNUNET_OK;
930 : }
931 0 : GNUNET_break (0);
932 0 : GNUNET_free (bm);
933 0 : return GNUNET_SYSERR;
934 : }
935 :
936 :
937 : /**
938 : * Function called to clean up memory allocated
939 : * by a #GNUNET_PQ_ResultConverter.
940 : *
941 : * @param cls closure
942 : * @param rd result data to clean up
943 : */
944 : static void
945 0 : clean_blinded_planchet (void *cls,
946 : void *rd)
947 : {
948 0 : struct TALER_BlindedPlanchet *bp = rd;
949 :
950 : (void) cls;
951 0 : TALER_blinded_planchet_free (bp);
952 0 : }
953 :
954 :
955 : struct GNUNET_PQ_ResultSpec
956 0 : TALER_PQ_result_spec_blinded_planchet (
957 : const char *name,
958 : struct TALER_BlindedPlanchet *bp)
959 : {
960 0 : struct GNUNET_PQ_ResultSpec res = {
961 : .conv = &extract_blinded_planchet,
962 : .cleaner = &clean_blinded_planchet,
963 : .dst = (void *) bp,
964 : .fname = name
965 : };
966 :
967 0 : return res;
968 : }
969 :
970 :
971 : /**
972 : * Extract data from a Postgres database @a result at row @a row.
973 : *
974 : * @param cls closure
975 : * @param result where to extract data from
976 : * @param row row to extract data from
977 : * @param fname name (or prefix) of the fields to extract from
978 : * @param[in,out] dst_size where to store size of result, may be NULL
979 : * @param[out] dst where to store the result
980 : * @return
981 : * #GNUNET_YES if all results could be extracted
982 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
983 : */
984 : static enum GNUNET_GenericReturnValue
985 0 : extract_exchange_withdraw_values (void *cls,
986 : PGresult *result,
987 : int row,
988 : const char *fname,
989 : size_t *dst_size,
990 : void *dst)
991 : {
992 0 : struct TALER_ExchangeBlindingValues *alg_values = dst;
993 : struct GNUNET_CRYPTO_BlindingInputValues *bi;
994 : size_t len;
995 : const char *res;
996 : int fnum;
997 : uint32_t be[2];
998 :
999 : (void) cls;
1000 : (void) dst_size;
1001 0 : fnum = PQfnumber (result,
1002 : fname);
1003 0 : if (fnum < 0)
1004 : {
1005 0 : GNUNET_break (0);
1006 0 : return GNUNET_SYSERR;
1007 : }
1008 0 : if (PQgetisnull (result,
1009 : row,
1010 : fnum))
1011 0 : return GNUNET_NO;
1012 :
1013 : /* if a field is null, continue but
1014 : * remember that we now return a different result */
1015 0 : len = PQgetlength (result,
1016 : row,
1017 : fnum);
1018 0 : res = PQgetvalue (result,
1019 : row,
1020 : fnum);
1021 0 : if (len < sizeof (be))
1022 : {
1023 0 : GNUNET_break (0);
1024 0 : return GNUNET_SYSERR;
1025 : }
1026 0 : GNUNET_memcpy (&be,
1027 : res,
1028 : sizeof (be));
1029 0 : if (0x010000 != ntohl (be[1])) /* magic marker: EWV */
1030 : {
1031 0 : GNUNET_break (0);
1032 0 : return GNUNET_SYSERR;
1033 : }
1034 0 : res += sizeof (be);
1035 0 : len -= sizeof (be);
1036 0 : bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
1037 0 : bi->rc = 1;
1038 0 : bi->cipher = ntohl (be[0]);
1039 0 : switch (bi->cipher)
1040 : {
1041 0 : case GNUNET_CRYPTO_BSA_INVALID:
1042 0 : break;
1043 0 : case GNUNET_CRYPTO_BSA_RSA:
1044 0 : if (0 != len)
1045 : {
1046 0 : GNUNET_break (0);
1047 0 : GNUNET_free (bi);
1048 0 : return GNUNET_SYSERR;
1049 : }
1050 0 : alg_values->blinding_inputs = bi;
1051 0 : return GNUNET_OK;
1052 0 : case GNUNET_CRYPTO_BSA_CS:
1053 0 : if (sizeof (bi->details.cs_values) != len)
1054 : {
1055 0 : GNUNET_break (0);
1056 0 : GNUNET_free (bi);
1057 0 : return GNUNET_SYSERR;
1058 : }
1059 0 : GNUNET_memcpy (&bi->details.cs_values,
1060 : res,
1061 : len);
1062 0 : alg_values->blinding_inputs = bi;
1063 0 : return GNUNET_OK;
1064 : }
1065 0 : GNUNET_break (0);
1066 0 : GNUNET_free (bi);
1067 0 : return GNUNET_SYSERR;
1068 : }
1069 :
1070 :
1071 : struct GNUNET_PQ_ResultSpec
1072 0 : TALER_PQ_result_spec_exchange_withdraw_values (
1073 : const char *name,
1074 : struct TALER_ExchangeBlindingValues *ewv)
1075 : {
1076 0 : struct GNUNET_PQ_ResultSpec res = {
1077 : .conv = &extract_exchange_withdraw_values,
1078 : .dst = (void *) ewv,
1079 : .fname = name
1080 : };
1081 :
1082 0 : return res;
1083 : }
1084 :
1085 :
1086 : /**
1087 : * Closure for the array result specifications. Contains type information
1088 : * for the generic parser extract_array_generic and out-pointers for the results.
1089 : */
1090 : struct ArrayResultCls
1091 : {
1092 : /**
1093 : * Oid of the expected type, must match the oid in the header of the PQResult struct
1094 : */
1095 : Oid oid;
1096 :
1097 : /**
1098 : * Target type
1099 : */
1100 : enum TALER_PQ_ArrayType typ;
1101 :
1102 : /**
1103 : * If not 0, defines the expected size of each entry
1104 : */
1105 : size_t same_size;
1106 :
1107 : /**
1108 : * Out-pointer to write the number of elements in the array
1109 : */
1110 : size_t *num;
1111 :
1112 : /**
1113 : * Out-pointer. If @a typ is TALER_PQ_array_of_byte and @a same_size is 0,
1114 : * allocate and put the array of @a num sizes here. NULL otherwise
1115 : */
1116 : size_t **sizes;
1117 :
1118 : /**
1119 : * DB_connection, needed for OID-lookup for composite types
1120 : */
1121 : const struct GNUNET_PQ_Context *db;
1122 :
1123 : /**
1124 : * Currency information for amount composites
1125 : */
1126 : char currency[TALER_CURRENCY_LEN];
1127 : };
1128 :
1129 :
1130 : /**
1131 : * Extract data from a Postgres database @a result as array of a specific type
1132 : * from row @a row. The type information and optionally additional
1133 : * out-parameters are given in @a cls which is of type array_result_cls.
1134 : *
1135 : * @param cls closure of type array_result_cls
1136 : * @param result where to extract data from
1137 : * @param row row to extract data from
1138 : * @param fname name (or prefix) of the fields to extract from
1139 : * @param[in,out] dst_size where to store size of result, may be NULL
1140 : * @param[out] dst where to store the result
1141 : * @return
1142 : * #GNUNET_YES if all results could be extracted
1143 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
1144 : */
1145 : static enum GNUNET_GenericReturnValue
1146 72 : extract_array_generic (
1147 : void *cls,
1148 : PGresult *result,
1149 : int row,
1150 : const char *fname,
1151 : size_t *dst_size,
1152 : void *dst)
1153 : {
1154 72 : const struct ArrayResultCls *info = cls;
1155 : int data_sz;
1156 : char *data;
1157 72 : void *out = NULL;
1158 : struct GNUNET_PQ_ArrayHeader_P header;
1159 : int col_num;
1160 :
1161 72 : GNUNET_assert (NULL != dst);
1162 72 : *((void **) dst) = NULL;
1163 :
1164 : #define FAIL_IF(cond) \
1165 : do { \
1166 : if ((cond)) \
1167 : { \
1168 : GNUNET_break (! (cond)); \
1169 : goto FAIL; \
1170 : } \
1171 : } while (0)
1172 :
1173 72 : col_num = PQfnumber (result, fname);
1174 72 : FAIL_IF (0 > col_num);
1175 :
1176 72 : if (PQgetisnull (result, row, col_num))
1177 : {
1178 23 : return GNUNET_NO;
1179 : }
1180 :
1181 49 : data_sz = PQgetlength (result, row, col_num);
1182 49 : FAIL_IF (0 > data_sz);
1183 49 : FAIL_IF (sizeof(header) > (size_t) data_sz);
1184 :
1185 49 : data = PQgetvalue (result, row, col_num);
1186 49 : FAIL_IF (NULL == data);
1187 :
1188 : {
1189 49 : struct GNUNET_PQ_ArrayHeader_P *h =
1190 : (struct GNUNET_PQ_ArrayHeader_P *) data;
1191 :
1192 49 : header.ndim = ntohl (h->ndim);
1193 49 : header.has_null = ntohl (h->has_null);
1194 49 : header.oid = ntohl (h->oid);
1195 49 : header.dim = ntohl (h->dim);
1196 49 : header.lbound = ntohl (h->lbound);
1197 :
1198 49 : FAIL_IF (1 != header.ndim);
1199 49 : FAIL_IF (INT_MAX <= header.dim);
1200 49 : FAIL_IF (0 != header.has_null);
1201 49 : FAIL_IF (1 != header.lbound);
1202 49 : FAIL_IF (info->oid != header.oid);
1203 : }
1204 :
1205 49 : if (NULL != info->num)
1206 49 : *info->num = header.dim;
1207 :
1208 : {
1209 49 : char *in = data + sizeof(header);
1210 :
1211 49 : switch (info->typ)
1212 : {
1213 1 : case TALER_PQ_array_of_amount:
1214 : {
1215 : struct TALER_Amount *amounts;
1216 1 : if (NULL != dst_size)
1217 1 : *dst_size = sizeof(struct TALER_Amount) * (header.dim);
1218 :
1219 1 : amounts = GNUNET_new_array (header.dim,
1220 : struct TALER_Amount);
1221 1 : *((void **) dst) = amounts;
1222 :
1223 4 : for (uint32_t i = 0; i < header.dim; i++)
1224 : {
1225 : struct TALER_PQ_AmountP ap;
1226 3 : struct TALER_Amount *amount = &amounts[i];
1227 : uint32_t val;
1228 : size_t sz;
1229 :
1230 3 : GNUNET_memcpy (&val,
1231 : in,
1232 : sizeof(val));
1233 3 : sz = ntohl (val);
1234 3 : in += sizeof(val);
1235 :
1236 : /* total size for this array-entry */
1237 3 : FAIL_IF (sizeof(ap) != sz);
1238 :
1239 3 : GNUNET_memcpy (&ap,
1240 : in,
1241 : sz);
1242 3 : FAIL_IF (2 != ntohl (ap.cnt));
1243 :
1244 3 : amount->value = GNUNET_ntohll (ap.v);
1245 3 : amount->fraction = ntohl (ap.f);
1246 3 : GNUNET_memcpy (amount->currency,
1247 : info->currency,
1248 : TALER_CURRENCY_LEN);
1249 :
1250 3 : in += sizeof(struct TALER_PQ_AmountP);
1251 : }
1252 1 : return GNUNET_OK;
1253 : }
1254 7 : case TALER_PQ_array_of_denom_hash:
1255 7 : if (NULL != dst_size)
1256 7 : *dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim);
1257 7 : out = GNUNET_new_array (header.dim,
1258 : struct TALER_DenominationHashP);
1259 7 : *((void **) dst) = out;
1260 16 : for (uint32_t i = 0; i < header.dim; i++)
1261 : {
1262 : uint32_t val;
1263 : size_t sz;
1264 :
1265 9 : GNUNET_memcpy (&val,
1266 : in,
1267 : sizeof(val));
1268 9 : sz = ntohl (val);
1269 9 : FAIL_IF (sz != sizeof(struct TALER_DenominationHashP));
1270 9 : in += sizeof(uint32_t);
1271 9 : *(struct TALER_DenominationHashP *) out =
1272 : *(struct TALER_DenominationHashP *) in;
1273 9 : in += sz;
1274 9 : out += sz;
1275 : }
1276 7 : return GNUNET_OK;
1277 :
1278 1 : case TALER_PQ_array_of_hash_code:
1279 1 : if (NULL != dst_size)
1280 1 : *dst_size = sizeof(struct GNUNET_HashCode) * (header.dim);
1281 1 : out = GNUNET_new_array (header.dim,
1282 : struct GNUNET_HashCode);
1283 1 : *((void **) dst) = out;
1284 3 : for (uint32_t i = 0; i < header.dim; i++)
1285 : {
1286 : uint32_t val;
1287 : size_t sz;
1288 :
1289 2 : GNUNET_memcpy (&val,
1290 : in,
1291 : sizeof(val));
1292 2 : sz = ntohl (val);
1293 2 : FAIL_IF (sz != sizeof(struct GNUNET_HashCode));
1294 2 : in += sizeof(uint32_t);
1295 2 : *(struct GNUNET_HashCode *) out =
1296 : *(struct GNUNET_HashCode *) in;
1297 2 : in += sz;
1298 2 : out += sz;
1299 : }
1300 1 : return GNUNET_OK;
1301 :
1302 0 : case TALER_PQ_array_of_blinded_coin_hash:
1303 0 : if (NULL != dst_size)
1304 0 : *dst_size = sizeof(struct TALER_BlindedCoinHashP) * (header.dim);
1305 0 : out = GNUNET_new_array (header.dim,
1306 : struct TALER_BlindedCoinHashP);
1307 0 : *((void **) dst) = out;
1308 0 : for (uint32_t i = 0; i < header.dim; i++)
1309 : {
1310 : uint32_t val;
1311 : size_t sz;
1312 :
1313 0 : GNUNET_memcpy (&val,
1314 : in,
1315 : sizeof(val));
1316 0 : sz = ntohl (val);
1317 0 : FAIL_IF (sz != sizeof(struct TALER_BlindedCoinHashP));
1318 0 : in += sizeof(uint32_t);
1319 0 : *(struct TALER_BlindedCoinHashP *) out =
1320 : *(struct TALER_BlindedCoinHashP *) in;
1321 0 : in += sz;
1322 0 : out += sz;
1323 : }
1324 0 : return GNUNET_OK;
1325 :
1326 9 : case TALER_PQ_array_of_cs_r_pub:
1327 9 : if (NULL != dst_size)
1328 9 : *dst_size = sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * (header.dim);
1329 9 : out = GNUNET_new_array (header.dim,
1330 : struct GNUNET_CRYPTO_CSPublicRPairP);
1331 9 : *((void **) dst) = out;
1332 45 : for (uint32_t i = 0; i < header.dim; i++)
1333 : {
1334 : uint32_t val;
1335 : size_t sz;
1336 :
1337 36 : GNUNET_memcpy (&val,
1338 : in,
1339 : sizeof(val));
1340 36 : sz = ntohl (val);
1341 36 : FAIL_IF (sz != sizeof(struct GNUNET_CRYPTO_CSPublicRPairP));
1342 36 : in += sizeof(uint32_t);
1343 36 : *(struct GNUNET_CRYPTO_CSPublicRPairP *) out =
1344 : *(struct GNUNET_CRYPTO_CSPublicRPairP *) in;
1345 36 : in += sz;
1346 36 : out += sz;
1347 : }
1348 9 : return GNUNET_OK;
1349 :
1350 31 : case TALER_PQ_array_of_blinded_denom_sig:
1351 : {
1352 : struct TALER_BlindedDenominationSignature *denom_sigs;
1353 31 : if (0 == header.dim)
1354 : {
1355 0 : if (NULL != dst_size)
1356 0 : *dst_size = 0;
1357 0 : break;
1358 : }
1359 :
1360 31 : denom_sigs = GNUNET_new_array (header.dim,
1361 : struct TALER_BlindedDenominationSignature);
1362 31 : *((void **) dst) = denom_sigs;
1363 :
1364 : /* copy data */
1365 252 : for (uint32_t i = 0; i < header.dim; i++)
1366 : {
1367 221 : struct TALER_BlindedDenominationSignature *denom_sig = &denom_sigs[i];
1368 : struct GNUNET_CRYPTO_BlindedSignature *bs;
1369 : uint32_t be[2];
1370 : uint32_t val;
1371 : size_t sz;
1372 :
1373 221 : GNUNET_memcpy (&val,
1374 : in,
1375 : sizeof(val));
1376 221 : sz = ntohl (val);
1377 221 : FAIL_IF (sizeof(be) > sz);
1378 :
1379 221 : in += sizeof(val);
1380 221 : GNUNET_memcpy (&be,
1381 : in,
1382 : sizeof(be));
1383 221 : FAIL_IF (0x01 != ntohl (be[1])); /* magic marker: blinded */
1384 :
1385 221 : in += sizeof(be);
1386 221 : sz -= sizeof(be);
1387 221 : bs = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
1388 221 : bs->cipher = ntohl (be[0]);
1389 221 : bs->rc = 1;
1390 221 : switch (bs->cipher)
1391 : {
1392 190 : case GNUNET_CRYPTO_BSA_RSA:
1393 : bs->details.blinded_rsa_signature
1394 190 : = GNUNET_CRYPTO_rsa_signature_decode (in,
1395 : sz);
1396 190 : if (NULL == bs->details.blinded_rsa_signature)
1397 : {
1398 0 : GNUNET_free (bs);
1399 0 : FAIL_IF (true);
1400 : }
1401 190 : break;
1402 31 : case GNUNET_CRYPTO_BSA_CS:
1403 31 : if (sizeof(bs->details.blinded_cs_answer) != sz)
1404 : {
1405 0 : GNUNET_free (bs);
1406 0 : FAIL_IF (true);
1407 : }
1408 31 : GNUNET_memcpy (&bs->details.blinded_cs_answer,
1409 : in,
1410 : sz);
1411 31 : break;
1412 0 : default:
1413 0 : GNUNET_free (bs);
1414 0 : FAIL_IF (true);
1415 : }
1416 221 : denom_sig->blinded_sig = bs;
1417 221 : in += sz;
1418 : }
1419 31 : return GNUNET_OK;
1420 : }
1421 0 : default:
1422 0 : FAIL_IF (true);
1423 : }
1424 : }
1425 0 : FAIL:
1426 0 : GNUNET_free (*(void **) dst);
1427 0 : return GNUNET_SYSERR;
1428 : #undef FAIL_IF
1429 : }
1430 :
1431 :
1432 : /**
1433 : * Cleanup of the data and closure of an array spec.
1434 : */
1435 : static void
1436 112 : array_cleanup (void *cls,
1437 : void *rd)
1438 : {
1439 112 : struct ArrayResultCls *info = cls;
1440 112 : void **dst = rd;
1441 :
1442 112 : if ( (0 == info->same_size) &&
1443 112 : (NULL != info->sizes) )
1444 0 : GNUNET_free (*(info->sizes));
1445 :
1446 : /* Clean up signatures, if applicable */
1447 112 : if ((TALER_PQ_array_of_blinded_denom_sig == info->typ) &&
1448 51 : (NULL != *dst))
1449 : {
1450 6 : struct TALER_BlindedDenominationSignature *denom_sigs = *dst;
1451 :
1452 6 : GNUNET_assert (NULL != info->num);
1453 76 : for (size_t i = 0; i < *info->num; i++)
1454 70 : GNUNET_free (denom_sigs[i].blinded_sig);
1455 : }
1456 112 : GNUNET_free (info);
1457 112 : GNUNET_free (*dst);
1458 112 : *dst = NULL;
1459 112 : }
1460 :
1461 :
1462 : struct GNUNET_PQ_ResultSpec
1463 51 : TALER_PQ_result_spec_array_blinded_denom_sig (
1464 : struct GNUNET_PQ_Context *db,
1465 : const char *name,
1466 : size_t *num,
1467 : struct TALER_BlindedDenominationSignature **denom_sigs)
1468 : {
1469 51 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1470 :
1471 51 : info->num = num;
1472 51 : info->typ = TALER_PQ_array_of_blinded_denom_sig;
1473 51 : GNUNET_assert (GNUNET_OK ==
1474 : GNUNET_PQ_get_oid_by_name (db,
1475 : "bytea",
1476 : &info->oid));
1477 : {
1478 51 : struct GNUNET_PQ_ResultSpec res = {
1479 : .conv = extract_array_generic,
1480 : .cleaner = &array_cleanup,
1481 : .dst = (void *) denom_sigs,
1482 : .fname = name,
1483 : .cls = info
1484 : };
1485 :
1486 51 : return res;
1487 : }
1488 : }
1489 :
1490 :
1491 : struct GNUNET_PQ_ResultSpec
1492 0 : TALER_PQ_result_spec_array_blinded_coin_hash (
1493 : struct GNUNET_PQ_Context *db,
1494 : const char *name,
1495 : size_t *num,
1496 : struct TALER_BlindedCoinHashP **h_coin_evs)
1497 : {
1498 0 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1499 :
1500 0 : info->num = num;
1501 0 : info->typ = TALER_PQ_array_of_blinded_coin_hash;
1502 0 : GNUNET_assert (GNUNET_OK ==
1503 : GNUNET_PQ_get_oid_by_name (db,
1504 : "bytea",
1505 : &info->oid));
1506 : {
1507 0 : struct GNUNET_PQ_ResultSpec res = {
1508 : .conv = extract_array_generic,
1509 : .cleaner = &array_cleanup,
1510 : .dst = (void *) h_coin_evs,
1511 : .fname = name,
1512 : .cls = info
1513 : };
1514 :
1515 0 : return res;
1516 : }
1517 : }
1518 :
1519 :
1520 : struct GNUNET_PQ_ResultSpec
1521 7 : TALER_PQ_result_spec_array_denom_hash (
1522 : struct GNUNET_PQ_Context *db,
1523 : const char *name,
1524 : size_t *num,
1525 : struct TALER_DenominationHashP **denom_hs)
1526 : {
1527 7 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1528 :
1529 7 : info->num = num;
1530 7 : info->typ = TALER_PQ_array_of_denom_hash;
1531 7 : GNUNET_assert (GNUNET_OK ==
1532 : GNUNET_PQ_get_oid_by_name (db,
1533 : "bytea",
1534 : &info->oid));
1535 : {
1536 7 : struct GNUNET_PQ_ResultSpec res = {
1537 : .conv = extract_array_generic,
1538 : .cleaner = &array_cleanup,
1539 : .dst = (void *) denom_hs,
1540 : .fname = name,
1541 : .cls = info
1542 : };
1543 :
1544 7 : return res;
1545 : }
1546 : }
1547 :
1548 :
1549 : struct GNUNET_PQ_ResultSpec
1550 1 : TALER_PQ_result_spec_array_amount (
1551 : struct GNUNET_PQ_Context *db,
1552 : const char *name,
1553 : const char *currency,
1554 : size_t *num,
1555 : struct TALER_Amount **amounts)
1556 : {
1557 1 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1558 :
1559 1 : info->num = num;
1560 1 : info->typ = TALER_PQ_array_of_amount;
1561 1 : info->db = db;
1562 1 : GNUNET_assert (GNUNET_OK ==
1563 : GNUNET_PQ_get_oid_by_name (db,
1564 : "taler_amount",
1565 : &info->oid));
1566 :
1567 : {
1568 1 : size_t clen = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
1569 : strlen (currency));
1570 1 : GNUNET_memcpy (&info->currency,
1571 : currency,
1572 : clen);
1573 : }
1574 : {
1575 1 : struct GNUNET_PQ_ResultSpec res = {
1576 : .conv = extract_array_generic,
1577 : .cleaner = &array_cleanup,
1578 : .dst = (void *) amounts,
1579 : .fname = name,
1580 : .cls = info,
1581 : };
1582 :
1583 1 : return res;
1584 : }
1585 : }
1586 :
1587 :
1588 : struct GNUNET_PQ_ResultSpec
1589 1 : TALER_PQ_result_spec_array_hash_code (
1590 : struct GNUNET_PQ_Context *db,
1591 : const char *name,
1592 : size_t *num,
1593 : struct GNUNET_HashCode **hashes)
1594 : {
1595 1 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1596 :
1597 1 : info->num = num;
1598 1 : info->typ = TALER_PQ_array_of_hash_code;
1599 1 : info->db = db;
1600 1 : GNUNET_assert (GNUNET_OK ==
1601 : GNUNET_PQ_get_oid_by_name (db,
1602 : "gnunet_hashcode",
1603 : &info->oid));
1604 : {
1605 1 : struct GNUNET_PQ_ResultSpec res = {
1606 : .conv = extract_array_generic,
1607 : .cleaner = &array_cleanup,
1608 : .dst = (void *) hashes,
1609 : .fname = name,
1610 : .cls = info,
1611 : };
1612 :
1613 1 : return res;
1614 : }
1615 : }
1616 :
1617 :
1618 : struct GNUNET_PQ_ResultSpec
1619 52 : TALER_PQ_result_spec_array_cs_r_pub (
1620 : struct GNUNET_PQ_Context *db,
1621 : const char *name,
1622 : size_t *num,
1623 : struct GNUNET_CRYPTO_CSPublicRPairP **cs_r_pubs)
1624 : {
1625 52 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1626 :
1627 52 : info->num = num;
1628 52 : info->typ = TALER_PQ_array_of_cs_r_pub;
1629 52 : GNUNET_assert (GNUNET_OK ==
1630 : GNUNET_PQ_get_oid_by_name (db,
1631 : "bytea",
1632 : &info->oid));
1633 : {
1634 52 : struct GNUNET_PQ_ResultSpec res = {
1635 : .conv = extract_array_generic,
1636 : .cleaner = &array_cleanup,
1637 : .dst = (void *) cs_r_pubs,
1638 : .fname = name,
1639 : .cls = info
1640 : };
1641 :
1642 52 : return res;
1643 : }
1644 : }
1645 :
1646 :
1647 : /* end of pq_result_helper.c */
|