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