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 "taler/platform.h"
22 : #include <gnunet/gnunet_util_lib.h>
23 : #include "pq_common.h"
24 : #include "taler/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 317 : extract_json (void *cls,
340 : PGresult *result,
341 : int row,
342 : const char *fname,
343 : size_t *dst_size,
344 : void *dst)
345 : {
346 317 : 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 317 : fnum = PQfnumber (result,
355 : fname);
356 317 : 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 317 : if (PQgetisnull (result,
364 : row,
365 : fnum))
366 144 : return GNUNET_NO;
367 173 : slen = PQgetlength (result,
368 : row,
369 : fnum);
370 173 : res = (const char *) PQgetvalue (result,
371 : row,
372 : fnum);
373 173 : *j_dst = json_loadb (res,
374 : slen,
375 : JSON_REJECT_DUPLICATES,
376 : &json_error);
377 173 : 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 173 : 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 68 : clean_json (void *cls,
399 : void *rd)
400 : {
401 68 : json_t **dst = rd;
402 :
403 : (void) cls;
404 68 : if (NULL != *dst)
405 : {
406 63 : json_decref (*dst);
407 63 : *dst = NULL;
408 : }
409 68 : }
410 :
411 :
412 : struct GNUNET_PQ_ResultSpec
413 367 : TALER_PQ_result_spec_json (const char *name,
414 : json_t **jp)
415 : {
416 367 : struct GNUNET_PQ_ResultSpec res = {
417 : .conv = &extract_json,
418 : .cleaner = &clean_json,
419 : .dst = (void *) jp,
420 : .fname = name
421 : };
422 :
423 367 : 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 : // FIXME: use GNUNET_PQ_result_spec_blinded_sig()
828 0 : struct GNUNET_PQ_ResultSpec res = {
829 : .conv = &extract_blinded_denom_sig,
830 : .cleaner = &clean_blinded_denom_sig,
831 : .dst = (void *) denom_sig,
832 : .fname = name
833 : };
834 :
835 0 : return res;
836 : }
837 :
838 :
839 : /**
840 : * Extract data from a Postgres database @a result at row @a row.
841 : *
842 : * @param cls closure
843 : * @param result where to extract data from
844 : * @param row the row to extract data from
845 : * @param fname name (or prefix) of the fields to extract from
846 : * @param[in,out] dst_size where to store size of result, may be NULL
847 : * @param[out] dst where to store the result
848 : * @return
849 : * #GNUNET_YES if all results could be extracted
850 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
851 : */
852 : static enum GNUNET_GenericReturnValue
853 0 : extract_blinded_planchet (void *cls,
854 : PGresult *result,
855 : int row,
856 : const char *fname,
857 : size_t *dst_size,
858 : void *dst)
859 : {
860 0 : struct TALER_BlindedPlanchet *bp = dst;
861 : struct GNUNET_CRYPTO_BlindedMessage *bm;
862 : size_t len;
863 : const char *res;
864 : int fnum;
865 : uint32_t be[2];
866 :
867 : (void) cls;
868 : (void) dst_size;
869 0 : fnum = PQfnumber (result,
870 : fname);
871 0 : if (fnum < 0)
872 : {
873 0 : GNUNET_break (0);
874 0 : return GNUNET_SYSERR;
875 : }
876 0 : if (PQgetisnull (result,
877 : row,
878 : fnum))
879 0 : return GNUNET_NO;
880 :
881 : /* if a field is null, continue but
882 : * remember that we now return a different result */
883 0 : len = PQgetlength (result,
884 : row,
885 : fnum);
886 0 : res = PQgetvalue (result,
887 : row,
888 : fnum);
889 0 : if (len < sizeof (be))
890 : {
891 0 : GNUNET_break (0);
892 0 : return GNUNET_SYSERR;
893 : }
894 0 : GNUNET_memcpy (&be,
895 : res,
896 : sizeof (be));
897 0 : if (0x0100 != ntohl (be[1])) /* magic marker: blinded */
898 : {
899 0 : GNUNET_break (0);
900 0 : return GNUNET_SYSERR;
901 : }
902 0 : res += sizeof (be);
903 0 : len -= sizeof (be);
904 0 : bm = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
905 0 : bm->rc = 1;
906 0 : bm->cipher = ntohl (be[0]);
907 0 : switch (bm->cipher)
908 : {
909 0 : case GNUNET_CRYPTO_BSA_INVALID:
910 0 : break;
911 0 : case GNUNET_CRYPTO_BSA_RSA:
912 : bm->details.rsa_blinded_message.blinded_msg_size
913 0 : = len;
914 : bm->details.rsa_blinded_message.blinded_msg
915 0 : = GNUNET_memdup (res,
916 : len);
917 0 : bp->blinded_message = bm;
918 0 : return GNUNET_OK;
919 0 : case GNUNET_CRYPTO_BSA_CS:
920 0 : if (sizeof (bm->details.cs_blinded_message) != len)
921 : {
922 0 : GNUNET_break (0);
923 0 : GNUNET_free (bm);
924 0 : return GNUNET_SYSERR;
925 : }
926 0 : GNUNET_memcpy (&bm->details.cs_blinded_message,
927 : res,
928 : len);
929 0 : bp->blinded_message = bm;
930 0 : return GNUNET_OK;
931 : }
932 0 : GNUNET_break (0);
933 0 : GNUNET_free (bm);
934 0 : return GNUNET_SYSERR;
935 : }
936 :
937 :
938 : /**
939 : * Function called to clean up memory allocated
940 : * by a #GNUNET_PQ_ResultConverter.
941 : *
942 : * @param cls closure
943 : * @param rd result data to clean up
944 : */
945 : static void
946 0 : clean_blinded_planchet (void *cls,
947 : void *rd)
948 : {
949 0 : struct TALER_BlindedPlanchet *bp = rd;
950 :
951 : (void) cls;
952 0 : TALER_blinded_planchet_free (bp);
953 0 : }
954 :
955 :
956 : struct GNUNET_PQ_ResultSpec
957 0 : TALER_PQ_result_spec_blinded_planchet (
958 : const char *name,
959 : struct TALER_BlindedPlanchet *bp)
960 : {
961 0 : struct GNUNET_PQ_ResultSpec res = {
962 : .conv = &extract_blinded_planchet,
963 : .cleaner = &clean_blinded_planchet,
964 : .dst = (void *) bp,
965 : .fname = name
966 : };
967 :
968 0 : return res;
969 : }
970 :
971 :
972 : /**
973 : * Extract data from a Postgres database @a result at row @a row.
974 : *
975 : * @param cls closure
976 : * @param result where to extract data from
977 : * @param row row to extract data from
978 : * @param fname name (or prefix) of the fields to extract from
979 : * @param[in,out] dst_size where to store size of result, may be NULL
980 : * @param[out] dst where to store the result
981 : * @return
982 : * #GNUNET_YES if all results could be extracted
983 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
984 : */
985 : static enum GNUNET_GenericReturnValue
986 0 : extract_exchange_withdraw_values (void *cls,
987 : PGresult *result,
988 : int row,
989 : const char *fname,
990 : size_t *dst_size,
991 : void *dst)
992 : {
993 0 : struct TALER_ExchangeBlindingValues *alg_values = dst;
994 : struct GNUNET_CRYPTO_BlindingInputValues *bi;
995 : size_t len;
996 : const char *res;
997 : int fnum;
998 : uint32_t be[2];
999 :
1000 : (void) cls;
1001 : (void) dst_size;
1002 0 : fnum = PQfnumber (result,
1003 : fname);
1004 0 : if (fnum < 0)
1005 : {
1006 0 : GNUNET_break (0);
1007 0 : return GNUNET_SYSERR;
1008 : }
1009 0 : if (PQgetisnull (result,
1010 : row,
1011 : fnum))
1012 0 : return GNUNET_NO;
1013 :
1014 : /* if a field is null, continue but
1015 : * remember that we now return a different result */
1016 0 : len = PQgetlength (result,
1017 : row,
1018 : fnum);
1019 0 : res = PQgetvalue (result,
1020 : row,
1021 : fnum);
1022 0 : if (len < sizeof (be))
1023 : {
1024 0 : GNUNET_break (0);
1025 0 : return GNUNET_SYSERR;
1026 : }
1027 0 : GNUNET_memcpy (&be,
1028 : res,
1029 : sizeof (be));
1030 0 : if (0x010000 != ntohl (be[1])) /* magic marker: EWV */
1031 : {
1032 0 : GNUNET_break (0);
1033 0 : return GNUNET_SYSERR;
1034 : }
1035 0 : res += sizeof (be);
1036 0 : len -= sizeof (be);
1037 0 : bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
1038 0 : bi->rc = 1;
1039 0 : bi->cipher = ntohl (be[0]);
1040 0 : switch (bi->cipher)
1041 : {
1042 0 : case GNUNET_CRYPTO_BSA_INVALID:
1043 0 : break;
1044 0 : case GNUNET_CRYPTO_BSA_RSA:
1045 0 : if (0 != len)
1046 : {
1047 0 : GNUNET_break (0);
1048 0 : GNUNET_free (bi);
1049 0 : return GNUNET_SYSERR;
1050 : }
1051 0 : alg_values->blinding_inputs = bi;
1052 0 : return GNUNET_OK;
1053 0 : case GNUNET_CRYPTO_BSA_CS:
1054 0 : if (sizeof (bi->details.cs_values) != len)
1055 : {
1056 0 : GNUNET_break (0);
1057 0 : GNUNET_free (bi);
1058 0 : return GNUNET_SYSERR;
1059 : }
1060 0 : GNUNET_memcpy (&bi->details.cs_values,
1061 : res,
1062 : len);
1063 0 : alg_values->blinding_inputs = bi;
1064 0 : return GNUNET_OK;
1065 : }
1066 0 : GNUNET_break (0);
1067 0 : GNUNET_free (bi);
1068 0 : return GNUNET_SYSERR;
1069 : }
1070 :
1071 :
1072 : struct GNUNET_PQ_ResultSpec
1073 0 : TALER_PQ_result_spec_exchange_withdraw_values (
1074 : const char *name,
1075 : struct TALER_ExchangeBlindingValues *ewv)
1076 : {
1077 0 : struct GNUNET_PQ_ResultSpec res = {
1078 : .conv = &extract_exchange_withdraw_values,
1079 : .dst = (void *) ewv,
1080 : .fname = name
1081 : };
1082 :
1083 0 : return res;
1084 : }
1085 :
1086 :
1087 : /**
1088 : * Closure for the array result specifications. Contains type information
1089 : * for the generic parser extract_array_generic and out-pointers for the results.
1090 : */
1091 : struct ArrayResultCls
1092 : {
1093 : /**
1094 : * Oid of the expected type, must match the oid in the header of the PQResult struct
1095 : */
1096 : Oid oid;
1097 :
1098 : /**
1099 : * Target type
1100 : */
1101 : enum TALER_PQ_ArrayType typ;
1102 :
1103 : /**
1104 : * If not 0, defines the expected size of each entry
1105 : */
1106 : size_t same_size;
1107 :
1108 : /**
1109 : * Out-pointer to write the number of elements in the array
1110 : */
1111 : size_t *num;
1112 :
1113 : /**
1114 : * Out-pointer. If @a typ is TALER_PQ_array_of_byte and @a same_size is 0,
1115 : * allocate and put the array of @a num sizes here. NULL otherwise
1116 : */
1117 : size_t **sizes;
1118 :
1119 : /**
1120 : * DB_connection, needed for OID-lookup for composite types
1121 : */
1122 : const struct GNUNET_PQ_Context *db;
1123 :
1124 : /**
1125 : * Currency information for amount composites
1126 : */
1127 : char currency[TALER_CURRENCY_LEN];
1128 : };
1129 :
1130 :
1131 : /**
1132 : * Extract data from a Postgres database @a result as array of a specific type
1133 : * from row @a row. The type information and optionally additional
1134 : * out-parameters are given in @a cls which is of type array_result_cls.
1135 : *
1136 : * @param cls closure of type array_result_cls
1137 : * @param result where to extract data from
1138 : * @param row row to extract data from
1139 : * @param fname name (or prefix) of the fields to extract from
1140 : * @param[in,out] dst_size where to store size of result, may be NULL
1141 : * @param[out] dst where to store the result
1142 : * @return
1143 : * #GNUNET_YES if all results could be extracted
1144 : * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
1145 : */
1146 : static enum GNUNET_GenericReturnValue
1147 72 : extract_array_generic (
1148 : void *cls,
1149 : PGresult *result,
1150 : int row,
1151 : const char *fname,
1152 : size_t *dst_size,
1153 : void *dst)
1154 : {
1155 72 : const struct ArrayResultCls *info = cls;
1156 : int data_sz;
1157 : char *data;
1158 72 : void *out = NULL;
1159 : struct GNUNET_PQ_ArrayHeader_P header;
1160 : int col_num;
1161 :
1162 72 : GNUNET_assert (NULL != dst);
1163 72 : *((void **) dst) = NULL;
1164 :
1165 : #define FAIL_IF(cond) \
1166 : do { \
1167 : if ((cond)) \
1168 : { \
1169 : GNUNET_break (! (cond)); \
1170 : goto FAIL; \
1171 : } \
1172 : } while (0)
1173 :
1174 72 : col_num = PQfnumber (result, fname);
1175 72 : FAIL_IF (0 > col_num);
1176 :
1177 72 : if (PQgetisnull (result, row, col_num))
1178 : {
1179 23 : return GNUNET_NO;
1180 : }
1181 :
1182 49 : data_sz = PQgetlength (result, row, col_num);
1183 49 : FAIL_IF (0 > data_sz);
1184 49 : FAIL_IF (sizeof(header) > (size_t) data_sz);
1185 :
1186 49 : data = PQgetvalue (result, row, col_num);
1187 49 : FAIL_IF (NULL == data);
1188 :
1189 : {
1190 49 : struct GNUNET_PQ_ArrayHeader_P *h =
1191 : (struct GNUNET_PQ_ArrayHeader_P *) data;
1192 :
1193 49 : header.ndim = ntohl (h->ndim);
1194 49 : header.has_null = ntohl (h->has_null);
1195 49 : header.oid = ntohl (h->oid);
1196 49 : header.dim = ntohl (h->dim);
1197 49 : header.lbound = ntohl (h->lbound);
1198 :
1199 49 : FAIL_IF (1 != header.ndim);
1200 49 : FAIL_IF (INT_MAX <= header.dim);
1201 49 : FAIL_IF (0 != header.has_null);
1202 49 : FAIL_IF (1 != header.lbound);
1203 49 : FAIL_IF (info->oid != header.oid);
1204 : }
1205 :
1206 49 : if (NULL != info->num)
1207 49 : *info->num = header.dim;
1208 :
1209 : {
1210 49 : char *in = data + sizeof(header);
1211 :
1212 49 : switch (info->typ)
1213 : {
1214 1 : case TALER_PQ_array_of_amount:
1215 : {
1216 : struct TALER_Amount *amounts;
1217 1 : if (NULL != dst_size)
1218 1 : *dst_size = sizeof(struct TALER_Amount) * (header.dim);
1219 :
1220 1 : amounts = GNUNET_new_array (header.dim,
1221 : struct TALER_Amount);
1222 1 : *((void **) dst) = amounts;
1223 :
1224 4 : for (uint32_t i = 0; i < header.dim; i++)
1225 : {
1226 : struct TALER_PQ_AmountP ap;
1227 3 : struct TALER_Amount *amount = &amounts[i];
1228 : uint32_t val;
1229 : size_t sz;
1230 :
1231 3 : GNUNET_memcpy (&val,
1232 : in,
1233 : sizeof(val));
1234 3 : sz = ntohl (val);
1235 3 : in += sizeof(val);
1236 :
1237 : /* total size for this array-entry */
1238 3 : FAIL_IF (sizeof(ap) != sz);
1239 :
1240 3 : GNUNET_memcpy (&ap,
1241 : in,
1242 : sz);
1243 3 : FAIL_IF (2 != ntohl (ap.cnt));
1244 :
1245 3 : amount->value = GNUNET_ntohll (ap.v);
1246 3 : amount->fraction = ntohl (ap.f);
1247 3 : GNUNET_memcpy (amount->currency,
1248 : info->currency,
1249 : TALER_CURRENCY_LEN);
1250 :
1251 3 : in += sizeof(struct TALER_PQ_AmountP);
1252 : }
1253 1 : return GNUNET_OK;
1254 : }
1255 7 : case TALER_PQ_array_of_denom_hash:
1256 7 : if (NULL != dst_size)
1257 7 : *dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim);
1258 7 : out = GNUNET_new_array (header.dim,
1259 : struct TALER_DenominationHashP);
1260 7 : *((void **) dst) = out;
1261 16 : for (uint32_t i = 0; i < header.dim; i++)
1262 : {
1263 : uint32_t val;
1264 : size_t sz;
1265 :
1266 9 : GNUNET_memcpy (&val,
1267 : in,
1268 : sizeof(val));
1269 9 : sz = ntohl (val);
1270 9 : FAIL_IF (sz != sizeof(struct TALER_DenominationHashP));
1271 9 : in += sizeof(uint32_t);
1272 9 : *(struct TALER_DenominationHashP *) out =
1273 : *(struct TALER_DenominationHashP *) in;
1274 9 : in += sz;
1275 9 : out += sz;
1276 : }
1277 7 : return GNUNET_OK;
1278 :
1279 1 : case TALER_PQ_array_of_hash_code:
1280 1 : if (NULL != dst_size)
1281 1 : *dst_size = sizeof(struct GNUNET_HashCode) * (header.dim);
1282 1 : out = GNUNET_new_array (header.dim,
1283 : struct GNUNET_HashCode);
1284 1 : *((void **) dst) = out;
1285 3 : for (uint32_t i = 0; i < header.dim; i++)
1286 : {
1287 : uint32_t val;
1288 : size_t sz;
1289 :
1290 2 : GNUNET_memcpy (&val,
1291 : in,
1292 : sizeof(val));
1293 2 : sz = ntohl (val);
1294 2 : FAIL_IF (sz != sizeof(struct GNUNET_HashCode));
1295 2 : in += sizeof(uint32_t);
1296 2 : *(struct GNUNET_HashCode *) out =
1297 : *(struct GNUNET_HashCode *) in;
1298 2 : in += sz;
1299 2 : out += sz;
1300 : }
1301 1 : return GNUNET_OK;
1302 :
1303 0 : case TALER_PQ_array_of_blinded_coin_hash:
1304 0 : if (NULL != dst_size)
1305 0 : *dst_size = sizeof(struct TALER_BlindedCoinHashP) * (header.dim);
1306 0 : out = GNUNET_new_array (header.dim,
1307 : struct TALER_BlindedCoinHashP);
1308 0 : *((void **) dst) = out;
1309 0 : for (uint32_t i = 0; i < header.dim; i++)
1310 : {
1311 : uint32_t val;
1312 : size_t sz;
1313 :
1314 0 : GNUNET_memcpy (&val,
1315 : in,
1316 : sizeof(val));
1317 0 : sz = ntohl (val);
1318 0 : FAIL_IF (sz != sizeof(struct TALER_BlindedCoinHashP));
1319 0 : in += sizeof(uint32_t);
1320 0 : *(struct TALER_BlindedCoinHashP *) out =
1321 : *(struct TALER_BlindedCoinHashP *) in;
1322 0 : in += sz;
1323 0 : out += sz;
1324 : }
1325 0 : return GNUNET_OK;
1326 :
1327 9 : case TALER_PQ_array_of_cs_r_pub:
1328 9 : if (NULL != dst_size)
1329 9 : *dst_size = sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * (header.dim);
1330 9 : out = GNUNET_new_array (header.dim,
1331 : struct GNUNET_CRYPTO_CSPublicRPairP);
1332 9 : *((void **) dst) = out;
1333 45 : for (uint32_t i = 0; i < header.dim; i++)
1334 : {
1335 : uint32_t val;
1336 : size_t sz;
1337 :
1338 36 : GNUNET_memcpy (&val,
1339 : in,
1340 : sizeof(val));
1341 36 : sz = ntohl (val);
1342 36 : FAIL_IF (sz != sizeof(struct GNUNET_CRYPTO_CSPublicRPairP));
1343 36 : in += sizeof(uint32_t);
1344 36 : *(struct GNUNET_CRYPTO_CSPublicRPairP *) out =
1345 : *(struct GNUNET_CRYPTO_CSPublicRPairP *) in;
1346 36 : in += sz;
1347 36 : out += sz;
1348 : }
1349 9 : return GNUNET_OK;
1350 :
1351 31 : case TALER_PQ_array_of_blinded_denom_sig:
1352 : {
1353 : struct TALER_BlindedDenominationSignature *denom_sigs;
1354 31 : if (0 == header.dim)
1355 : {
1356 0 : if (NULL != dst_size)
1357 0 : *dst_size = 0;
1358 0 : break;
1359 : }
1360 :
1361 31 : denom_sigs = GNUNET_new_array (header.dim,
1362 : struct TALER_BlindedDenominationSignature);
1363 31 : *((void **) dst) = denom_sigs;
1364 :
1365 : /* copy data */
1366 252 : for (uint32_t i = 0; i < header.dim; i++)
1367 : {
1368 221 : struct TALER_BlindedDenominationSignature *denom_sig = &denom_sigs[i];
1369 : struct GNUNET_CRYPTO_BlindedSignature *bs;
1370 : uint32_t be[2];
1371 : uint32_t val;
1372 : size_t sz;
1373 :
1374 221 : GNUNET_memcpy (&val,
1375 : in,
1376 : sizeof(val));
1377 221 : sz = ntohl (val);
1378 221 : FAIL_IF (sizeof(be) > sz);
1379 :
1380 221 : in += sizeof(val);
1381 221 : GNUNET_memcpy (&be,
1382 : in,
1383 : sizeof(be));
1384 221 : FAIL_IF (0x01 != ntohl (be[1])); /* magic marker: blinded */
1385 :
1386 221 : in += sizeof(be);
1387 221 : sz -= sizeof(be);
1388 221 : bs = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
1389 221 : bs->cipher = ntohl (be[0]);
1390 221 : bs->rc = 1;
1391 221 : switch (bs->cipher)
1392 : {
1393 190 : case GNUNET_CRYPTO_BSA_RSA:
1394 : bs->details.blinded_rsa_signature
1395 190 : = GNUNET_CRYPTO_rsa_signature_decode (in,
1396 : sz);
1397 190 : if (NULL == bs->details.blinded_rsa_signature)
1398 : {
1399 0 : GNUNET_free (bs);
1400 0 : FAIL_IF (true);
1401 : }
1402 190 : break;
1403 31 : case GNUNET_CRYPTO_BSA_CS:
1404 31 : if (sizeof(bs->details.blinded_cs_answer) != sz)
1405 : {
1406 0 : GNUNET_free (bs);
1407 0 : FAIL_IF (true);
1408 : }
1409 31 : GNUNET_memcpy (&bs->details.blinded_cs_answer,
1410 : in,
1411 : sz);
1412 31 : break;
1413 0 : default:
1414 0 : GNUNET_free (bs);
1415 0 : FAIL_IF (true);
1416 : }
1417 221 : denom_sig->blinded_sig = bs;
1418 221 : in += sz;
1419 : }
1420 31 : return GNUNET_OK;
1421 : }
1422 0 : default:
1423 0 : FAIL_IF (true);
1424 : }
1425 : }
1426 0 : FAIL:
1427 0 : GNUNET_free (*(void **) dst);
1428 0 : return GNUNET_SYSERR;
1429 : #undef FAIL_IF
1430 : }
1431 :
1432 :
1433 : /**
1434 : * Cleanup of the data and closure of an array spec.
1435 : */
1436 : static void
1437 112 : array_cleanup (void *cls,
1438 : void *rd)
1439 : {
1440 112 : struct ArrayResultCls *info = cls;
1441 112 : void **dst = rd;
1442 :
1443 112 : if ( (0 == info->same_size) &&
1444 112 : (NULL != info->sizes) )
1445 0 : GNUNET_free (*(info->sizes));
1446 :
1447 : /* Clean up signatures, if applicable */
1448 112 : if ((TALER_PQ_array_of_blinded_denom_sig == info->typ) &&
1449 51 : (NULL != *dst))
1450 : {
1451 6 : struct TALER_BlindedDenominationSignature *denom_sigs = *dst;
1452 :
1453 6 : GNUNET_assert (NULL != info->num);
1454 76 : for (size_t i = 0; i < *info->num; i++)
1455 70 : GNUNET_free (denom_sigs[i].blinded_sig);
1456 : }
1457 112 : GNUNET_free (info);
1458 112 : GNUNET_free (*dst);
1459 112 : *dst = NULL;
1460 112 : }
1461 :
1462 :
1463 : struct GNUNET_PQ_ResultSpec
1464 51 : TALER_PQ_result_spec_array_blinded_denom_sig (
1465 : struct GNUNET_PQ_Context *db,
1466 : const char *name,
1467 : size_t *num,
1468 : struct TALER_BlindedDenominationSignature **denom_sigs)
1469 : {
1470 51 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1471 :
1472 51 : info->num = num;
1473 51 : info->typ = TALER_PQ_array_of_blinded_denom_sig;
1474 51 : GNUNET_assert (GNUNET_OK ==
1475 : GNUNET_PQ_get_oid_by_name (db,
1476 : "bytea",
1477 : &info->oid));
1478 : {
1479 51 : struct GNUNET_PQ_ResultSpec res = {
1480 : .conv = extract_array_generic,
1481 : .cleaner = &array_cleanup,
1482 : .dst = (void *) denom_sigs,
1483 : .fname = name,
1484 : .cls = info
1485 : };
1486 :
1487 51 : return res;
1488 : }
1489 : }
1490 :
1491 :
1492 : struct GNUNET_PQ_ResultSpec
1493 0 : TALER_PQ_result_spec_array_blinded_coin_hash (
1494 : struct GNUNET_PQ_Context *db,
1495 : const char *name,
1496 : size_t *num,
1497 : struct TALER_BlindedCoinHashP **h_coin_evs)
1498 : {
1499 0 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1500 :
1501 0 : info->num = num;
1502 0 : info->typ = TALER_PQ_array_of_blinded_coin_hash;
1503 0 : GNUNET_assert (GNUNET_OK ==
1504 : GNUNET_PQ_get_oid_by_name (db,
1505 : "bytea",
1506 : &info->oid));
1507 : {
1508 0 : struct GNUNET_PQ_ResultSpec res = {
1509 : .conv = extract_array_generic,
1510 : .cleaner = &array_cleanup,
1511 : .dst = (void *) h_coin_evs,
1512 : .fname = name,
1513 : .cls = info
1514 : };
1515 :
1516 0 : return res;
1517 : }
1518 : }
1519 :
1520 :
1521 : struct GNUNET_PQ_ResultSpec
1522 7 : TALER_PQ_result_spec_array_denom_hash (
1523 : struct GNUNET_PQ_Context *db,
1524 : const char *name,
1525 : size_t *num,
1526 : struct TALER_DenominationHashP **denom_hs)
1527 : {
1528 7 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1529 :
1530 7 : info->num = num;
1531 7 : info->typ = TALER_PQ_array_of_denom_hash;
1532 7 : GNUNET_assert (GNUNET_OK ==
1533 : GNUNET_PQ_get_oid_by_name (db,
1534 : "bytea",
1535 : &info->oid));
1536 : {
1537 7 : struct GNUNET_PQ_ResultSpec res = {
1538 : .conv = extract_array_generic,
1539 : .cleaner = &array_cleanup,
1540 : .dst = (void *) denom_hs,
1541 : .fname = name,
1542 : .cls = info
1543 : };
1544 :
1545 7 : return res;
1546 : }
1547 : }
1548 :
1549 :
1550 : struct GNUNET_PQ_ResultSpec
1551 1 : TALER_PQ_result_spec_array_amount (
1552 : struct GNUNET_PQ_Context *db,
1553 : const char *name,
1554 : const char *currency,
1555 : size_t *num,
1556 : struct TALER_Amount **amounts)
1557 : {
1558 1 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1559 :
1560 1 : info->num = num;
1561 1 : info->typ = TALER_PQ_array_of_amount;
1562 1 : info->db = db;
1563 1 : GNUNET_assert (GNUNET_OK ==
1564 : GNUNET_PQ_get_oid_by_name (db,
1565 : "taler_amount",
1566 : &info->oid));
1567 :
1568 : {
1569 1 : size_t clen = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
1570 : strlen (currency));
1571 1 : GNUNET_memcpy (&info->currency,
1572 : currency,
1573 : clen);
1574 : }
1575 : {
1576 1 : struct GNUNET_PQ_ResultSpec res = {
1577 : .conv = extract_array_generic,
1578 : .cleaner = &array_cleanup,
1579 : .dst = (void *) amounts,
1580 : .fname = name,
1581 : .cls = info,
1582 : };
1583 :
1584 1 : return res;
1585 : }
1586 : }
1587 :
1588 :
1589 : struct GNUNET_PQ_ResultSpec
1590 1 : TALER_PQ_result_spec_array_hash_code (
1591 : struct GNUNET_PQ_Context *db,
1592 : const char *name,
1593 : size_t *num,
1594 : struct GNUNET_HashCode **hashes)
1595 : {
1596 1 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1597 :
1598 1 : info->num = num;
1599 1 : info->typ = TALER_PQ_array_of_hash_code;
1600 1 : info->db = db;
1601 1 : GNUNET_assert (GNUNET_OK ==
1602 : GNUNET_PQ_get_oid_by_name (db,
1603 : "gnunet_hashcode",
1604 : &info->oid));
1605 : {
1606 1 : struct GNUNET_PQ_ResultSpec res = {
1607 : .conv = extract_array_generic,
1608 : .cleaner = &array_cleanup,
1609 : .dst = (void *) hashes,
1610 : .fname = name,
1611 : .cls = info,
1612 : };
1613 :
1614 1 : return res;
1615 : }
1616 : }
1617 :
1618 :
1619 : struct GNUNET_PQ_ResultSpec
1620 52 : TALER_PQ_result_spec_array_cs_r_pub (
1621 : struct GNUNET_PQ_Context *db,
1622 : const char *name,
1623 : size_t *num,
1624 : struct GNUNET_CRYPTO_CSPublicRPairP **cs_r_pubs)
1625 : {
1626 52 : struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
1627 :
1628 52 : info->num = num;
1629 52 : info->typ = TALER_PQ_array_of_cs_r_pub;
1630 52 : GNUNET_assert (GNUNET_OK ==
1631 : GNUNET_PQ_get_oid_by_name (db,
1632 : "bytea",
1633 : &info->oid));
1634 : {
1635 52 : struct GNUNET_PQ_ResultSpec res = {
1636 : .conv = extract_array_generic,
1637 : .cleaner = &array_cleanup,
1638 : .dst = (void *) cs_r_pubs,
1639 : .fname = name,
1640 : .cls = info
1641 : };
1642 :
1643 52 : return res;
1644 : }
1645 : }
1646 :
1647 :
1648 : /* end of pq_result_helper.c */
|