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