LCOV - code coverage report
Current view: top level - json - json_pack.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 128 205 62.4 %
Date: 2025-06-22 12:09:43 Functions: 13 18 72.2 %

          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 */

Generated by: LCOV version 1.16