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