LCOV - code coverage report
Current view: top level - json - json_pack.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 62.4 % 221 138
Test Date: 2026-04-14 15:39:31 Functions: 68.4 % 19 13

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

Generated by: LCOV version 2.0-1