donau_json.c (16220B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 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/donau_json.c 18 * @brief helper functions for JSON processing using libjansson 19 * @author Lukas Matyja 20 */ 21 #include "donau_config.h" 22 #include <gnunet/gnunet_util_lib.h> 23 #include <taler/taler_util.h> 24 #include <taler/taler_json_lib.h> 25 #include <unistr.h> 26 #include "donau_json_lib.h" 27 28 /** 29 * Convert string value to numeric cipher value. 30 * 31 * @param cipher_s input string 32 * @return numeric cipher value 33 */ 34 static enum GNUNET_CRYPTO_BlindSignatureAlgorithm 35 string_to_cipher (const char *cipher_s) 36 { 37 if (0 == strcasecmp (cipher_s, 38 "RSA")) 39 return GNUNET_CRYPTO_BSA_RSA; 40 if (0 == strcasecmp (cipher_s, 41 "CS")) 42 return GNUNET_CRYPTO_BSA_CS; 43 return GNUNET_CRYPTO_BSA_INVALID; 44 } 45 46 47 /** 48 * Parse given JSON object partially into a donation unit public key. 49 * 50 * Depending on the cipher in cls, it parses the corresponding public key type. 51 * 52 * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm 53 * @param root the json object representing data 54 * @param[out] spec where to write the data 55 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 56 */ 57 static enum GNUNET_GenericReturnValue 58 parse_donation_unit_pub (void *cls, 59 json_t *root, 60 struct GNUNET_JSON_Specification *spec) 61 { 62 struct DONAU_DonationUnitPublicKey *donation_unit_pub = spec->ptr; 63 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 64 const char *cipher; 65 struct GNUNET_JSON_Specification dspec[] = { 66 GNUNET_JSON_spec_string ("cipher", 67 &cipher), 68 GNUNET_JSON_spec_end () 69 }; 70 const char *emsg; 71 unsigned int eline; 72 73 (void) cls; 74 if (GNUNET_OK != 75 GNUNET_JSON_parse (root, 76 dspec, 77 &emsg, 78 &eline)) 79 { 80 GNUNET_break_op (0); 81 return GNUNET_SYSERR; 82 } 83 84 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 85 bsign_pub->rc = 1; 86 bsign_pub->cipher = string_to_cipher (cipher); 87 switch (bsign_pub->cipher) 88 { 89 case GNUNET_CRYPTO_BSA_INVALID: 90 break; 91 case GNUNET_CRYPTO_BSA_RSA: 92 { 93 struct GNUNET_JSON_Specification ispec[] = { 94 GNUNET_JSON_spec_rsa_public_key ( 95 "rsa_public_key", 96 &bsign_pub->details.rsa_public_key), 97 GNUNET_JSON_spec_fixed_auto ( 98 "pub_key_hash", 99 &bsign_pub->pub_key_hash), 100 GNUNET_JSON_spec_end () 101 }; 102 103 if (GNUNET_OK != 104 GNUNET_JSON_parse (root, 105 ispec, 106 &emsg, 107 &eline)) 108 { 109 GNUNET_break_op (0); 110 GNUNET_free (bsign_pub); 111 return GNUNET_SYSERR; 112 } 113 donation_unit_pub->bsign_pub_key = bsign_pub; 114 return GNUNET_OK; 115 } 116 case GNUNET_CRYPTO_BSA_CS: 117 { 118 struct GNUNET_JSON_Specification ispec[] = { 119 GNUNET_JSON_spec_fixed ("cs_public_key", 120 &bsign_pub->details.cs_public_key, 121 sizeof (bsign_pub->details.cs_public_key)), 122 GNUNET_JSON_spec_fixed_auto ( 123 "pub_key_hash", 124 &bsign_pub->pub_key_hash), 125 GNUNET_JSON_spec_end () 126 }; 127 128 if (GNUNET_OK != 129 GNUNET_JSON_parse (root, 130 ispec, 131 &emsg, 132 &eline)) 133 { 134 GNUNET_break_op (0); 135 GNUNET_free (bsign_pub); 136 return GNUNET_SYSERR; 137 } 138 donation_unit_pub->bsign_pub_key = bsign_pub; 139 return GNUNET_OK; 140 } 141 } 142 GNUNET_break_op (0); 143 GNUNET_free (bsign_pub); 144 return GNUNET_SYSERR; 145 } 146 147 148 /** 149 * Cleanup data left from parsing donation unit public key. 150 * 151 * @param cls closure, NULL 152 * @param[out] spec where to free the data 153 */ 154 static void 155 clean_donation_unit_pub (void *cls, 156 struct GNUNET_JSON_Specification *spec) 157 { 158 struct DONAU_DonationUnitPublicKey *donation_unit_pub = spec->ptr; 159 160 (void) cls; 161 DONAU_donation_unit_pub_free (donation_unit_pub); 162 } 163 164 165 struct GNUNET_JSON_Specification 166 DONAU_JSON_spec_donation_unit_pub (const char *field, 167 struct DONAU_DonationUnitPublicKey *pk) 168 { 169 struct GNUNET_JSON_Specification ret = { 170 .parser = &parse_donation_unit_pub, 171 .cleaner = &clean_donation_unit_pub, 172 .field = field, 173 .ptr = pk 174 }; 175 176 return ret; 177 } 178 179 180 /** 181 * Parse given JSON object to blinded unique donation identifier. 182 * 183 * @param cls closure, NULL 184 * @param root the json object representing data 185 * @param[out] spec where to write the data 186 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 187 */ 188 static enum GNUNET_GenericReturnValue 189 parse_blinded_donation_identifier (void *cls, 190 json_t *root, 191 struct GNUNET_JSON_Specification *spec) 192 { 193 struct DONAU_BlindedUniqueDonorIdentifier *blinded_udi = spec->ptr; 194 struct GNUNET_CRYPTO_BlindedMessage *blinded_message; 195 const char *cipher; 196 struct GNUNET_JSON_Specification dspec[] = { 197 GNUNET_JSON_spec_string ("cipher", 198 &cipher), 199 GNUNET_JSON_spec_end () 200 }; 201 const char *emsg; 202 unsigned int eline; 203 204 (void) cls; 205 if (GNUNET_OK != 206 GNUNET_JSON_parse (root, 207 dspec, 208 &emsg, 209 &eline)) 210 { 211 GNUNET_break_op (0); 212 return GNUNET_SYSERR; 213 } 214 blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage); 215 blinded_message->rc = 1; 216 blinded_message->cipher = string_to_cipher (cipher); 217 switch (blinded_message->cipher) 218 { 219 case GNUNET_CRYPTO_BSA_INVALID: 220 break; 221 case GNUNET_CRYPTO_BSA_RSA: 222 { 223 struct GNUNET_JSON_Specification ispec[] = { 224 GNUNET_JSON_spec_varsize ( 225 "rsa_blinded_identifier", 226 &blinded_message->details.rsa_blinded_message.blinded_msg, 227 &blinded_message->details.rsa_blinded_message.blinded_msg_size), 228 GNUNET_JSON_spec_end () 229 }; 230 231 if (GNUNET_OK != 232 GNUNET_JSON_parse (root, 233 ispec, 234 &emsg, 235 &eline)) 236 { 237 GNUNET_break_op (0); 238 GNUNET_free (blinded_message); 239 return GNUNET_SYSERR; 240 } 241 blinded_udi->blinded_message = blinded_message; 242 return GNUNET_OK; 243 } 244 case GNUNET_CRYPTO_BSA_CS: 245 { 246 struct GNUNET_JSON_Specification ispec[] = { 247 GNUNET_JSON_spec_fixed_auto ( 248 "cs_nonce", 249 &blinded_message->details.cs_blinded_message.nonce), 250 GNUNET_JSON_spec_fixed_auto ( 251 "cs_blinded_c0", 252 &blinded_message->details.cs_blinded_message.c[0]), 253 GNUNET_JSON_spec_fixed_auto ( 254 "cs_blinded_c1", 255 &blinded_message->details.cs_blinded_message.c[1]), 256 GNUNET_JSON_spec_end () 257 }; 258 259 if (GNUNET_OK != 260 GNUNET_JSON_parse (root, 261 ispec, 262 &emsg, 263 &eline)) 264 { 265 GNUNET_break_op (0); 266 GNUNET_free (blinded_message); 267 return GNUNET_SYSERR; 268 } 269 blinded_udi->blinded_message = blinded_message; 270 return GNUNET_OK; 271 } 272 } 273 GNUNET_break_op (0); 274 GNUNET_free (blinded_message); 275 return GNUNET_SYSERR; 276 } 277 278 279 /** 280 * Cleanup data left from parsing blinded unique donation identifier. 281 * 282 * @param cls closure, NULL 283 * @param[out] spec where to free the data 284 */ 285 static void 286 clean_blinded_donation_identifier (void *cls, 287 struct GNUNET_JSON_Specification *spec) 288 { 289 struct TALER_BlindedPlanchet *blinded_udi = spec->ptr; 290 291 (void) cls; 292 TALER_blinded_planchet_free (blinded_udi); 293 } 294 295 296 struct GNUNET_JSON_Specification 297 DONAU_JSON_spec_blinded_donation_identifier (const char *field, 298 struct 299 DONAU_BlindedUniqueDonorIdentifier 300 * 301 blinded_udi) 302 { 303 struct GNUNET_JSON_Specification ret = { 304 .parser = &parse_blinded_donation_identifier, 305 .cleaner = &clean_blinded_donation_identifier, 306 .field = field, 307 .ptr = blinded_udi 308 }; 309 310 blinded_udi->blinded_message = NULL; 311 return ret; 312 } 313 314 315 /** 316 * Parse given JSON object to blinded donation unit signature. 317 * 318 * @param cls closure, NULL 319 * @param root the json object representing data 320 * @param[out] spec where to write the data 321 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 322 */ 323 static enum GNUNET_GenericReturnValue 324 parse_blinded_donation_unit_sig (void *cls, 325 json_t *root, 326 struct GNUNET_JSON_Specification *spec) 327 { 328 struct DONAU_BlindedDonationUnitSignature *du_sig = spec->ptr; 329 struct GNUNET_CRYPTO_BlindedSignature *blinded_sig; 330 const char *cipher; 331 struct GNUNET_JSON_Specification dspec[] = { 332 GNUNET_JSON_spec_string ("cipher", 333 &cipher), 334 GNUNET_JSON_spec_end () 335 }; 336 const char *emsg; 337 unsigned int eline; 338 339 (void) cls; 340 if (GNUNET_OK != 341 GNUNET_JSON_parse (root, 342 dspec, 343 &emsg, 344 &eline)) 345 { 346 GNUNET_break_op (0); 347 return GNUNET_SYSERR; 348 } 349 blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); 350 blinded_sig->cipher = string_to_cipher (cipher); 351 blinded_sig->rc = 1; 352 switch (blinded_sig->cipher) 353 { 354 case GNUNET_CRYPTO_BSA_INVALID: 355 break; 356 case GNUNET_CRYPTO_BSA_RSA: 357 { 358 struct GNUNET_JSON_Specification ispec[] = { 359 GNUNET_JSON_spec_rsa_signature ( 360 "blinded_rsa_signature", 361 &blinded_sig->details.blinded_rsa_signature), 362 GNUNET_JSON_spec_end () 363 }; 364 365 if (GNUNET_OK != 366 GNUNET_JSON_parse (root, 367 ispec, 368 &emsg, 369 &eline)) 370 { 371 GNUNET_break_op (0); 372 GNUNET_free (blinded_sig); 373 return GNUNET_SYSERR; 374 } 375 du_sig->blinded_sig = blinded_sig; 376 return GNUNET_OK; 377 } 378 case GNUNET_CRYPTO_BSA_CS: 379 { 380 struct GNUNET_JSON_Specification ispec[] = { 381 GNUNET_JSON_spec_uint32 ("b", 382 &blinded_sig->details.blinded_cs_answer.b), 383 GNUNET_JSON_spec_fixed_auto ("s", 384 &blinded_sig->details.blinded_cs_answer. 385 s_scalar), 386 GNUNET_JSON_spec_end () 387 }; 388 389 if (GNUNET_OK != 390 GNUNET_JSON_parse (root, 391 ispec, 392 &emsg, 393 &eline)) 394 { 395 GNUNET_break_op (0); 396 GNUNET_free (blinded_sig); 397 return GNUNET_SYSERR; 398 } 399 du_sig->blinded_sig = blinded_sig; 400 return GNUNET_OK; 401 } 402 } 403 GNUNET_break_op (0); 404 GNUNET_free (blinded_sig); 405 return GNUNET_SYSERR; 406 } 407 408 409 /** 410 * Cleanup data left from parsing donation unit public key. 411 * 412 * @param cls closure, NULL 413 * @param[out] spec where to free the data 414 */ 415 static void 416 clean_blinded_donation_unit_sig (void *cls, 417 struct GNUNET_JSON_Specification *spec) 418 { 419 struct DONAU_BlindedDonationUnitSignature *du_sig = spec->ptr; 420 421 (void) cls; 422 DONAU_blinded_donation_unit_sig_free (du_sig); 423 } 424 425 426 struct GNUNET_JSON_Specification 427 DONAU_JSON_spec_blinded_donation_unit_sig (const char *field, 428 struct 429 DONAU_BlindedDonationUnitSignature * 430 sig) 431 { 432 struct GNUNET_JSON_Specification ret = { 433 .parser = &parse_blinded_donation_unit_sig, 434 .cleaner = &clean_blinded_donation_unit_sig, 435 .field = field, 436 .ptr = sig 437 }; 438 439 sig->blinded_sig = NULL; 440 return ret; 441 } 442 443 444 struct GNUNET_JSON_PackSpec 445 DONAU_JSON_pack_donation_unit_sig ( 446 const char *name, 447 const struct DONAU_DonationUnitSignature *sig) 448 { 449 const struct GNUNET_CRYPTO_UnblindedSignature *bs; 450 struct GNUNET_JSON_PackSpec ps = { 451 .field_name = name, 452 }; 453 454 if (NULL == sig) 455 return ps; 456 bs = sig->unblinded_sig; 457 switch (bs->cipher) 458 { 459 case GNUNET_CRYPTO_BSA_INVALID: 460 break; 461 case GNUNET_CRYPTO_BSA_RSA: 462 ps.object = GNUNET_JSON_PACK ( 463 GNUNET_JSON_pack_string ("cipher", 464 "RSA"), 465 GNUNET_JSON_pack_rsa_signature ("rsa_signature", 466 bs->details.rsa_signature)); 467 return ps; 468 case GNUNET_CRYPTO_BSA_CS: 469 ps.object = GNUNET_JSON_PACK ( 470 GNUNET_JSON_pack_string ("cipher", 471 "CS"), 472 GNUNET_JSON_pack_data_auto ("cs_signature_r", 473 &bs->details.cs_signature.r_point), 474 GNUNET_JSON_pack_data_auto ("cs_signature_s", 475 &bs->details.cs_signature.s_scalar)); 476 return ps; 477 } 478 GNUNET_assert (0); 479 return ps; 480 } 481 482 483 struct GNUNET_JSON_PackSpec 484 DONAU_JSON_pack_blinded_donation_unit_sig ( 485 const char *name, 486 const struct DONAU_BlindedDonationUnitSignature *sig) 487 { 488 const struct GNUNET_CRYPTO_BlindedSignature *bs; 489 struct GNUNET_JSON_PackSpec ps = { 490 .field_name = name, 491 }; 492 493 if (NULL == sig) 494 return ps; 495 bs = sig->blinded_sig; 496 switch (bs->cipher) 497 { 498 case GNUNET_CRYPTO_BSA_INVALID: 499 break; 500 case GNUNET_CRYPTO_BSA_RSA: 501 ps.object = GNUNET_JSON_PACK ( 502 GNUNET_JSON_pack_string ("cipher", 503 "RSA"), 504 GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature", 505 bs->details.blinded_rsa_signature)); 506 return ps; 507 case GNUNET_CRYPTO_BSA_CS: 508 ps.object = GNUNET_JSON_PACK ( 509 GNUNET_JSON_pack_string ("cipher", 510 "CS"), 511 GNUNET_JSON_pack_uint64 ("b", 512 bs->details.blinded_cs_answer.b), 513 GNUNET_JSON_pack_data_auto ("s", 514 &bs->details.blinded_cs_answer.s_scalar)); 515 return ps; 516 } 517 GNUNET_assert (0); 518 return ps; 519 } 520 521 522 struct GNUNET_JSON_PackSpec 523 DONAU_JSON_pack_blinded_donation_identifier ( 524 const char *name, 525 const struct DONAU_BlindedUniqueDonorIdentifier *blinded_udi) 526 { 527 const struct GNUNET_CRYPTO_BlindedMessage *bm; 528 struct GNUNET_JSON_PackSpec ps = { 529 .field_name = name, 530 }; 531 532 if (NULL == blinded_udi) 533 return ps; 534 bm = blinded_udi->blinded_message; 535 switch (bm->cipher) 536 { 537 case GNUNET_CRYPTO_BSA_INVALID: 538 break; 539 case GNUNET_CRYPTO_BSA_RSA: 540 ps.object = GNUNET_JSON_PACK ( 541 GNUNET_JSON_pack_string ("cipher", 542 "RSA"), 543 GNUNET_JSON_pack_data_varsize ( 544 "rsa_blinded_identifier", 545 bm->details.rsa_blinded_message.blinded_msg, 546 bm->details.rsa_blinded_message.blinded_msg_size)); 547 return ps; 548 case GNUNET_CRYPTO_BSA_CS: 549 ps.object = GNUNET_JSON_PACK ( 550 GNUNET_JSON_pack_string ("cipher", 551 "CS"), 552 GNUNET_JSON_pack_data_auto ( 553 "cs_nonce", 554 &bm->details.cs_blinded_message.nonce), 555 GNUNET_JSON_pack_data_auto ( 556 "cs_blinded_c0", 557 &bm->details.cs_blinded_message.c[0]), 558 GNUNET_JSON_pack_data_auto ( 559 "cs_blinded_c1", 560 &bm->details.cs_blinded_message.c[1])); 561 return ps; 562 } 563 GNUNET_assert (0); 564 return ps; 565 } 566 567 568 /* end of json/donau_json.c */