Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2021-2025 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 json/json_pack.c
18 : * @brief helper functions for JSON object packing
19 : * @author Christian Grothoff
20 : * @author Özgür Kesim
21 : */
22 : #include <gnunet/gnunet_util_lib.h>
23 : #include "taler/taler_util.h"
24 : #include "taler/taler_json_lib.h"
25 :
26 :
27 : struct GNUNET_JSON_PackSpec
28 0 : TALER_JSON_pack_time_abs_human (const char *name,
29 : struct GNUNET_TIME_Absolute at)
30 : {
31 0 : struct GNUNET_JSON_PackSpec ps = {
32 : .field_name = name,
33 0 : .object = json_string (
34 : GNUNET_STRINGS_absolute_time_to_string (at))
35 : };
36 :
37 0 : return ps;
38 : }
39 :
40 :
41 : struct GNUNET_JSON_PackSpec
42 25 : TALER_JSON_pack_econtract (
43 : const char *name,
44 : const struct TALER_EncryptedContract *econtract)
45 : {
46 25 : struct GNUNET_JSON_PackSpec ps = {
47 : .field_name = name,
48 : };
49 :
50 25 : if (NULL == econtract)
51 0 : return ps;
52 : ps.object
53 25 : = GNUNET_JSON_PACK (
54 : GNUNET_JSON_pack_data_varsize ("econtract",
55 : econtract->econtract,
56 : econtract->econtract_size),
57 : GNUNET_JSON_pack_data_auto ("econtract_sig",
58 : &econtract->econtract_sig),
59 : GNUNET_JSON_pack_data_auto ("contract_pub",
60 : &econtract->contract_pub));
61 25 : return ps;
62 : }
63 :
64 :
65 : struct GNUNET_JSON_PackSpec
66 8 : TALER_JSON_pack_age_commitment (
67 : const char *name,
68 : const struct TALER_AgeCommitment *age_commitment)
69 : {
70 8 : struct GNUNET_JSON_PackSpec ps = {
71 : .field_name = name,
72 : };
73 : json_t *keys;
74 :
75 8 : if (NULL == age_commitment ||
76 8 : 0 == age_commitment->num)
77 0 : return ps;
78 :
79 8 : GNUNET_assert (NULL !=
80 : (keys = json_array ()));
81 :
82 8 : for (size_t i = 0;
83 64 : i < age_commitment->num;
84 56 : i++)
85 : {
86 : json_t *val;
87 56 : val = GNUNET_JSON_from_data (&age_commitment->pubs[i],
88 : sizeof(age_commitment->pubs[i]));
89 56 : GNUNET_assert (NULL != val);
90 56 : GNUNET_assert (0 ==
91 : json_array_append_new (keys, val));
92 : }
93 :
94 8 : ps.object = keys;
95 8 : return ps;
96 : }
97 :
98 :
99 : struct GNUNET_JSON_PackSpec
100 89 : TALER_JSON_pack_kycte (const char *name,
101 : enum TALER_KYCLOGIC_KycTriggerEvent event)
102 : {
103 89 : const char *str = "INVALID";
104 :
105 89 : switch (event)
106 : {
107 1 : case TALER_KYCLOGIC_KYC_TRIGGER_NONE:
108 1 : str = "NONE";
109 1 : break;
110 12 : case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
111 12 : str = "WITHDRAW";
112 12 : break;
113 2 : case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
114 2 : str = "DEPOSIT";
115 2 : break;
116 8 : case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
117 8 : str = "MERGE";
118 8 : break;
119 10 : case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
120 10 : str = "BALANCE";
121 10 : break;
122 47 : case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
123 47 : str = "CLOSE";
124 47 : break;
125 9 : case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE:
126 9 : str = "AGGREGATE";
127 9 : break;
128 0 : case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION:
129 0 : str = "TRANSACTION";
130 0 : break;
131 0 : case TALER_KYCLOGIC_KYC_TRIGGER_REFUND:
132 0 : str = "REFUND";
133 0 : break;
134 : }
135 89 : return GNUNET_JSON_pack_string (name,
136 : str);
137 : }
138 :
139 :
140 : struct GNUNET_JSON_PackSpec
141 477 : TALER_JSON_pack_denom_pub (
142 : const char *name,
143 : const struct TALER_DenominationPublicKey *pk)
144 : {
145 : const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp;
146 477 : struct GNUNET_JSON_PackSpec ps = {
147 : .field_name = name,
148 : };
149 :
150 477 : if (NULL == pk)
151 0 : return ps;
152 477 : bsp = pk->bsign_pub_key;
153 477 : switch (bsp->cipher)
154 : {
155 0 : case GNUNET_CRYPTO_BSA_INVALID:
156 0 : break;
157 260 : case GNUNET_CRYPTO_BSA_RSA:
158 : ps.object
159 260 : = GNUNET_JSON_PACK (
160 : GNUNET_JSON_pack_string ("cipher",
161 : "RSA"),
162 : GNUNET_JSON_pack_uint64 ("age_mask",
163 : pk->age_mask.bits),
164 : GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
165 : bsp->details.rsa_public_key));
166 477 : return ps;
167 217 : case GNUNET_CRYPTO_BSA_CS:
168 : ps.object
169 217 : = GNUNET_JSON_PACK (
170 : GNUNET_JSON_pack_string ("cipher",
171 : "CS"),
172 : GNUNET_JSON_pack_uint64 ("age_mask",
173 : pk->age_mask.bits),
174 : GNUNET_JSON_pack_data_varsize ("cs_pub",
175 : &bsp->details.cs_public_key,
176 : sizeof (bsp->details.cs_public_key)));
177 217 : return ps;
178 : }
179 0 : GNUNET_assert (0);
180 : return ps;
181 : }
182 :
183 :
184 : struct GNUNET_JSON_PackSpec
185 0 : TALER_JSON_pack_token_pub (
186 : const char *name,
187 : const struct TALER_TokenIssuePublicKey *pk)
188 : {
189 : const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp;
190 0 : struct GNUNET_JSON_PackSpec ps = {
191 : .field_name = name,
192 : };
193 :
194 0 : if (NULL == pk)
195 0 : return ps;
196 0 : bsp = pk->public_key;
197 0 : switch (bsp->cipher)
198 : {
199 0 : case GNUNET_CRYPTO_BSA_INVALID:
200 0 : break;
201 0 : case GNUNET_CRYPTO_BSA_RSA:
202 : ps.object
203 0 : = GNUNET_JSON_PACK (
204 : GNUNET_JSON_pack_string ("cipher",
205 : "RSA"),
206 : GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
207 : bsp->details.rsa_public_key));
208 0 : return ps;
209 0 : case GNUNET_CRYPTO_BSA_CS:
210 : ps.object
211 0 : = GNUNET_JSON_PACK (
212 : GNUNET_JSON_pack_string ("cipher",
213 : "CS"),
214 : GNUNET_JSON_pack_data_varsize ("cs_pub",
215 : &bsp->details.cs_public_key,
216 : sizeof (bsp->details.cs_public_key)));
217 0 : return ps;
218 : }
219 0 : GNUNET_assert (0);
220 : return ps;
221 : }
222 :
223 :
224 : struct GNUNET_JSON_PackSpec
225 152 : TALER_JSON_pack_denom_sig (
226 : const char *name,
227 : const struct TALER_DenominationSignature *sig)
228 : {
229 152 : struct GNUNET_JSON_PackSpec ps = {
230 : .field_name = name,
231 : };
232 152 : if (NULL == sig)
233 0 : return ps;
234 152 : return GNUNET_JSON_pack_unblinded_signature (name,
235 152 : sig->unblinded_sig);
236 : }
237 :
238 :
239 : struct GNUNET_JSON_PackSpec
240 0 : TALER_JSON_pack_token_issue_sig (
241 : const char *name,
242 : const struct TALER_TokenIssueSignature *sig)
243 : {
244 0 : struct GNUNET_JSON_PackSpec ps = {
245 : .field_name = name,
246 : };
247 0 : if (NULL == sig)
248 0 : return ps;
249 0 : return GNUNET_JSON_pack_unblinded_signature (name,
250 0 : sig->signature);
251 : }
252 :
253 :
254 : struct GNUNET_JSON_PackSpec
255 0 : TALER_JSON_pack_token_envelope (
256 : const char *name,
257 : const struct TALER_TokenEnvelope *envelope)
258 : {
259 0 : struct GNUNET_JSON_PackSpec ps = {
260 : .field_name = name,
261 : };
262 :
263 0 : if (NULL == envelope)
264 0 : return ps;
265 0 : return GNUNET_JSON_pack_blinded_message (name,
266 0 : envelope->blinded_pub);
267 : }
268 :
269 :
270 : struct GNUNET_JSON_PackSpec
271 0 : TALER_JSON_pack_exchange_blinding_values (
272 : const char *name,
273 : const struct TALER_ExchangeBlindingValues *ewv)
274 : {
275 : const struct GNUNET_CRYPTO_BlindingInputValues *biv;
276 0 : struct GNUNET_JSON_PackSpec ps = {
277 : .field_name = name,
278 : };
279 :
280 0 : if (NULL == ewv)
281 0 : return ps;
282 0 : biv = ewv->blinding_inputs;
283 0 : switch (biv->cipher)
284 : {
285 0 : case GNUNET_CRYPTO_BSA_INVALID:
286 0 : break;
287 0 : case GNUNET_CRYPTO_BSA_RSA:
288 0 : ps.object = GNUNET_JSON_PACK (
289 : GNUNET_JSON_pack_string ("cipher",
290 : "RSA"));
291 0 : return ps;
292 0 : case GNUNET_CRYPTO_BSA_CS:
293 0 : ps.object = GNUNET_JSON_PACK (
294 : GNUNET_JSON_pack_string ("cipher",
295 : "CS"),
296 : GNUNET_JSON_pack_data_varsize (
297 : "r_pub_0",
298 : &biv->details.cs_values.r_pub[0],
299 : sizeof(struct GNUNET_CRYPTO_CsRPublic)),
300 : GNUNET_JSON_pack_data_varsize (
301 : "r_pub_1",
302 : &biv->details.cs_values.r_pub[1],
303 : sizeof(struct GNUNET_CRYPTO_CsRPublic))
304 : );
305 0 : return ps;
306 : }
307 0 : GNUNET_assert (0);
308 : return ps;
309 : }
310 :
311 :
312 : struct GNUNET_JSON_PackSpec
313 50 : TALER_JSON_pack_blinding_prepare_response (
314 : const char *name,
315 : const struct TALER_BlindingPrepareResponse *bpr)
316 : {
317 50 : struct GNUNET_JSON_PackSpec ps = {
318 : .field_name = name,
319 : };
320 50 : if (NULL == bpr)
321 0 : return ps;
322 50 : switch (bpr->cipher)
323 : {
324 0 : case GNUNET_CRYPTO_BSA_INVALID:
325 0 : break;
326 0 : case GNUNET_CRYPTO_BSA_RSA:
327 0 : ps.object = GNUNET_JSON_PACK (
328 : GNUNET_JSON_pack_string ("cipher",
329 : "RSA"));
330 50 : return ps;
331 50 : case GNUNET_CRYPTO_BSA_CS: {
332 50 : json_t *j_rpubs = json_array ();
333 :
334 50 : GNUNET_assert (NULL!=j_rpubs);
335 :
336 148 : for (size_t i = 0; i < bpr->num; i++)
337 : {
338 98 : struct GNUNET_CRYPTO_CSPublicRPairP *pair =
339 98 : &bpr->details.cs[i];
340 : json_t *j_pubs[2];
341 : json_t *j_pair;
342 :
343 98 : j_pair = json_array ();
344 98 : GNUNET_assert (NULL != j_pair);
345 :
346 196 : j_pubs[0] = GNUNET_JSON_from_data (
347 98 : &pair->r_pub[0],
348 : sizeof(pair->r_pub[0]));
349 98 : GNUNET_assert (NULL != j_pubs[0]);
350 :
351 196 : j_pubs[1] = GNUNET_JSON_from_data (
352 98 : &pair->r_pub[1],
353 : sizeof(pair->r_pub[1]));
354 98 : GNUNET_assert (NULL != j_pubs[1]);
355 :
356 98 : GNUNET_assert (0 == json_array_append_new (j_pair, j_pubs[0]));
357 98 : GNUNET_assert (0 == json_array_append_new (j_pair, j_pubs[1]));
358 98 : GNUNET_assert (0 == json_array_append_new (j_rpubs, j_pair));
359 : }
360 :
361 50 : ps.object = GNUNET_JSON_PACK (
362 : GNUNET_JSON_pack_string ("cipher", "CS"),
363 : GNUNET_JSON_pack_array_steal ("r_pubs", j_rpubs));
364 50 : return ps;
365 : }
366 : }
367 0 : GNUNET_assert (0);
368 : return ps;
369 : }
370 :
371 :
372 : struct GNUNET_JSON_PackSpec
373 126 : TALER_JSON_pack_blinded_denom_sig (
374 : const char *name,
375 : const struct TALER_BlindedDenominationSignature *sig)
376 : {
377 : const struct GNUNET_CRYPTO_BlindedSignature *bs;
378 126 : struct GNUNET_JSON_PackSpec ps = {
379 : .field_name = name,
380 : };
381 :
382 126 : if (NULL == sig)
383 0 : return ps;
384 126 : bs = sig->blinded_sig;
385 126 : switch (bs->cipher)
386 : {
387 0 : case GNUNET_CRYPTO_BSA_INVALID:
388 0 : break;
389 65 : case GNUNET_CRYPTO_BSA_RSA:
390 65 : ps.object = GNUNET_JSON_PACK (
391 : GNUNET_JSON_pack_string ("cipher",
392 : "RSA"),
393 : GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
394 : bs->details.blinded_rsa_signature));
395 126 : return ps;
396 61 : case GNUNET_CRYPTO_BSA_CS:
397 61 : ps.object = GNUNET_JSON_PACK (
398 : GNUNET_JSON_pack_string ("cipher",
399 : "CS"),
400 : GNUNET_JSON_pack_uint64 ("b",
401 : bs->details.blinded_cs_answer.b),
402 : GNUNET_JSON_pack_data_auto ("s",
403 : &bs->details.blinded_cs_answer.s_scalar));
404 61 : return ps;
405 : }
406 0 : GNUNET_assert (0);
407 : return ps;
408 : }
409 :
410 :
411 : struct GNUNET_JSON_PackSpec
412 459 : TALER_JSON_pack_blinded_planchet (
413 : const char *name,
414 : const struct TALER_BlindedPlanchet *blinded_planchet)
415 : {
416 459 : struct GNUNET_JSON_PackSpec ps = {
417 : .field_name = name,
418 : };
419 :
420 459 : if (NULL == blinded_planchet)
421 0 : return ps;
422 459 : return GNUNET_JSON_pack_blinded_message (name,
423 459 : blinded_planchet->blinded_message);
424 : }
425 :
426 :
427 : struct GNUNET_JSON_PackSpec
428 4966 : TALER_JSON_pack_amount (const char *name,
429 : const struct TALER_Amount *amount)
430 : {
431 9932 : struct GNUNET_JSON_PackSpec ps = {
432 : .field_name = name,
433 : .object = (NULL != amount)
434 4949 : ? TALER_JSON_from_amount (amount)
435 4966 : : NULL
436 : };
437 :
438 4966 : return ps;
439 : }
440 :
441 :
442 : struct GNUNET_JSON_PackSpec
443 1 : TALER_JSON_pack_amount_array (const char *name,
444 : size_t len,
445 : const struct TALER_Amount *amounts)
446 : {
447 1 : struct GNUNET_JSON_PackSpec ps = {
448 : .field_name = name,
449 : };
450 :
451 1 : if (NULL == amounts)
452 : {
453 0 : ps.object = json_null ();
454 0 : return ps;
455 : }
456 : {
457 1 : json_t *array = json_array ();
458 :
459 1 : GNUNET_assert (NULL != array);
460 3 : for (size_t i = 0; i<len; i++)
461 : {
462 : json_t *entry;
463 :
464 2 : char *amount_str = TALER_amount_to_string (&amounts[i]);
465 2 : GNUNET_assert (NULL != amount_str);
466 :
467 2 : entry = json_string (amount_str);
468 :
469 2 : GNUNET_free (amount_str);
470 2 : GNUNET_assert (NULL != entry);
471 2 : GNUNET_assert (0 ==
472 : json_array_append_new (array,
473 : entry));
474 : }
475 1 : ps.object = array;
476 : }
477 1 : return ps;
478 : }
479 :
480 :
481 : struct GNUNET_JSON_PackSpec
482 357 : TALER_JSON_pack_full_payto (
483 : const char *name,
484 : const struct TALER_FullPayto payto)
485 : {
486 714 : return GNUNET_JSON_pack_string (name,
487 357 : payto.full_payto);
488 : }
489 :
490 :
491 : struct GNUNET_JSON_PackSpec
492 6 : TALER_JSON_pack_normalized_payto (
493 : const char *name,
494 : const struct TALER_NormalizedPayto payto)
495 : {
496 12 : return GNUNET_JSON_pack_string (name,
497 6 : payto.normalized_payto);
498 : }
499 :
500 :
501 : struct GNUNET_JSON_PackSpec
502 0 : TALER_JSON_pack_tuple (
503 : const char *name,
504 : const struct GNUNET_JSON_PackSpec packers[])
505 : {
506 : static size_t max_packers = 256;
507 0 : struct GNUNET_JSON_PackSpec ps = {
508 : .field_name = name,
509 : };
510 : size_t idx;
511 0 : json_t *j_array = json_array ();
512 :
513 0 : GNUNET_assert (NULL!=j_array);
514 :
515 0 : for (idx = 0; idx < max_packers; idx++)
516 : {
517 0 : if (NULL == packers[idx].object)
518 0 : break;
519 :
520 0 : GNUNET_assert (0 ==
521 : json_array_append_new (j_array,
522 : packers[idx].object));
523 : }
524 :
525 0 : GNUNET_assert (idx != max_packers);
526 :
527 0 : ps.object = j_array;
528 0 : return ps;
529 :
530 : }
531 :
532 :
533 : struct GNUNET_JSON_PackSpec
534 130 : TALER_JSON_pack_array_of_data (
535 : const char *name,
536 : size_t num,
537 : const void *data,
538 : size_t size)
539 : {
540 130 : const char *blob = data;
541 130 : struct GNUNET_JSON_PackSpec ps = {
542 : .field_name = name,
543 : };
544 130 : json_t *j_array = json_array ();
545 :
546 130 : GNUNET_assert (NULL!=j_array);
547 130 : if (0 == num)
548 : {
549 3 : ps.object = j_array;
550 3 : return ps;
551 : }
552 127 : GNUNET_assert ((0 == size) ||
553 : (num == 1) ||
554 : (num * size > size));
555 :
556 616 : for (size_t idx = 0; idx < num; idx++)
557 : {
558 489 : GNUNET_assert (0 ==
559 : json_array_append_new (
560 : j_array,
561 : GNUNET_JSON_from_data (
562 : blob,
563 : size)));
564 489 : blob += size;
565 : }
566 :
567 127 : ps.object = j_array;
568 127 : return ps;
569 : }
570 :
571 :
572 : /* End of json/json_pack.c */
|