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