LCOV - code coverage report
Current view: top level - util - crypto_contract.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.3 % 202 140
Test Date: 2026-09-11 18:55:36 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2022 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 util/crypto_contract.c
      18              :  * @brief functions for encrypting and decrypting contracts for P2P payments
      19              :  * @author Christian Grothoff <christian@grothoff.org>
      20              :  */
      21              : #include "taler/taler_util.h"
      22              : #include <zlib.h>
      23              : 
      24              : 
      25              : /**
      26              :  * Different types of contracts supported.
      27              :  */
      28              : enum ContractFormats
      29              : {
      30              :   /**
      31              :    * The encrypted contract represents a payment offer. The receiver
      32              :    * can merge it into a reserve/account to accept the contract and
      33              :    * obtain the payment.
      34              :    */
      35              :   TALER_EXCHANGE_CONTRACT_PAYMENT_OFFER = 0,
      36              : 
      37              :   /**
      38              :    * The encrypted contract represents a payment request.
      39              :    */
      40              :   TALER_EXCHANGE_CONTRACT_PAYMENT_REQUEST = 1
      41              : };
      42              : 
      43              : 
      44              : /**
      45              :  * Nonce used for encryption, 24 bytes.
      46              :  */
      47              : struct NonceP
      48              : {
      49              :   uint8_t nonce[crypto_secretbox_NONCEBYTES];
      50              : };
      51              : 
      52              : /**
      53              :  * Specifies a key used for symmetric encryption, 32 bytes.
      54              :  */
      55              : struct SymKeyP
      56              : {
      57              :   uint32_t key[8];
      58              : };
      59              : 
      60              : 
      61              : /**
      62              :  * Compute @a key.
      63              :  *
      64              :  * @param key_material key for calculation
      65              :  * @param key_m_len length of key
      66              :  * @param nonce nonce for calculation
      67              :  * @param salt salt value for calculation
      68              :  * @param[out] key where to write the en-/description key
      69              :  */
      70              : static void
      71           75 : derive_key (const void *key_material,
      72              :             size_t key_m_len,
      73              :             const struct NonceP *nonce,
      74              :             const char *salt,
      75              :             struct SymKeyP *key)
      76              : {
      77           75 :   GNUNET_assert (GNUNET_YES ==
      78              :                  GNUNET_CRYPTO_hkdf_gnunet (
      79              :                    key,
      80              :                    sizeof (*key),
      81              :                    /* salt / XTS */
      82              :                    nonce,
      83              :                    sizeof (*nonce),
      84              :                    /* ikm */
      85              :                    key_material,
      86              :                    key_m_len,
      87              :                    /* info chunks */
      88              :                    /* The "salt" passed here is actually not something random,
      89              :                       but a protocol-specific identifier string.  Thus
      90              :                       we pass it as a context info to the HKDF */
      91              :                    GNUNET_CRYPTO_kdf_arg_string (salt)));
      92           75 : }
      93              : 
      94              : 
      95              : /**
      96              :  * Encryption of data.
      97              :  *
      98              :  * @param nonce value to use for the nonce
      99              :  * @param key key which is used to derive a key/iv pair from
     100              :  * @param key_len length of key
     101              :  * @param data data to encrypt
     102              :  * @param data_size size of the data
     103              :  * @param salt salt value which is used for key derivation
     104              :  * @param[out] res ciphertext output
     105              :  * @param[out] res_size size of the ciphertext
     106              :  */
     107              : static void
     108           40 : blob_encrypt (const struct NonceP *nonce,
     109              :               const void *key,
     110              :               size_t key_len,
     111              :               const void *data,
     112              :               size_t data_size,
     113              :               const char *salt,
     114              :               void **res,
     115              :               size_t *res_size)
     116              : {
     117              :   size_t ciphertext_size;
     118              :   struct SymKeyP skey;
     119              : 
     120           40 :   derive_key (key,
     121              :               key_len,
     122              :               nonce,
     123              :               salt,
     124              :               &skey);
     125           40 :   ciphertext_size = crypto_secretbox_NONCEBYTES
     126              :                     + crypto_secretbox_MACBYTES
     127              :                     + data_size;
     128           40 :   *res_size = ciphertext_size;
     129           40 :   *res = GNUNET_malloc (ciphertext_size);
     130           40 :   GNUNET_memcpy (*res,
     131              :                  nonce,
     132              :                  crypto_secretbox_NONCEBYTES);
     133           40 :   GNUNET_assert (0 ==
     134              :                  crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES,
     135              :                                         data,
     136              :                                         data_size,
     137              :                                         (void *) nonce,
     138              :                                         (void *) &skey));
     139           40 : }
     140              : 
     141              : 
     142              : /**
     143              :  * Decryption of data like encrypted recovery document etc.
     144              :  *
     145              :  * @param key key which is used to derive a key/iv pair from
     146              :  * @param key_len length of key
     147              :  * @param data data to decrypt
     148              :  * @param data_size size of the data
     149              :  * @param salt salt value which is used for key derivation
     150              :  * @param[out] res plaintext output
     151              :  * @param[out] res_size size of the plaintext
     152              :  * @return #GNUNET_OK on success
     153              :  */
     154              : static enum GNUNET_GenericReturnValue
     155           35 : blob_decrypt (const void *key,
     156              :               size_t key_len,
     157              :               const void *data,
     158              :               size_t data_size,
     159              :               const char *salt,
     160              :               void **res,
     161              :               size_t *res_size)
     162              : {
     163              :   const struct NonceP *nonce;
     164              :   struct SymKeyP skey;
     165              :   size_t plaintext_size;
     166              : 
     167           35 :   if (data_size < crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES)
     168              :   {
     169            0 :     GNUNET_break (0);
     170            0 :     return GNUNET_SYSERR;
     171              :   }
     172           35 :   nonce = data;
     173           35 :   derive_key (key,
     174              :               key_len,
     175              :               nonce,
     176              :               salt,
     177              :               &skey);
     178           35 :   plaintext_size = data_size - (crypto_secretbox_NONCEBYTES
     179              :                                 + crypto_secretbox_MACBYTES);
     180           35 :   *res = GNUNET_malloc (plaintext_size);
     181           35 :   *res_size = plaintext_size;
     182           35 :   if (0 != crypto_secretbox_open_easy (*res,
     183           35 :                                        data + crypto_secretbox_NONCEBYTES,
     184           35 :                                        data_size - crypto_secretbox_NONCEBYTES,
     185              :                                        (void *) nonce,
     186              :                                        (void *) &skey))
     187              :   {
     188            0 :     GNUNET_break (0);
     189            0 :     GNUNET_free (*res);
     190            0 :     return GNUNET_SYSERR;
     191              :   }
     192           35 :   return GNUNET_OK;
     193              : }
     194              : 
     195              : 
     196              : /**
     197              :  * Header for encrypted contracts.
     198              :  */
     199              : struct ContractHeaderP
     200              : {
     201              :   /**
     202              :    * Type of the contract, in NBO.
     203              :    */
     204              :   uint32_t ctype;
     205              : 
     206              :   /**
     207              :    * Length of the encrypted contract, in NBO.
     208              :    */
     209              :   uint32_t clen;
     210              : };
     211              : 
     212              : 
     213              : /**
     214              :  * Header for encrypted contracts.
     215              :  */
     216              : struct ContractHeaderMergeP
     217              : {
     218              :   /**
     219              :    * Generic header.
     220              :    */
     221              :   struct ContractHeaderP header;
     222              : 
     223              :   /**
     224              :    * Private key with the merge capability.
     225              :    */
     226              :   struct TALER_PurseMergePrivateKeyP merge_priv;
     227              : };
     228              : 
     229              : 
     230              : /**
     231              :  * Salt we use when encrypting contracts for merge.
     232              :  */
     233              : #define MERGE_SALT "p2p-merge-contract"
     234              : 
     235              : 
     236              : void
     237           12 : TALER_CRYPTO_contract_encrypt_for_merge (
     238              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
     239              :   const struct TALER_ContractDiffiePrivateP *contract_priv,
     240              :   const struct TALER_PurseMergePrivateKeyP *merge_priv,
     241              :   const json_t *contract_terms,
     242              :   void **econtract,
     243              :   size_t *econtract_size)
     244              : {
     245              :   struct GNUNET_HashCode key;
     246              :   char *cstr;
     247              :   size_t clen;
     248              :   void *xbuf;
     249              :   struct ContractHeaderMergeP *hdr;
     250              :   struct NonceP nonce;
     251              :   uLongf cbuf_size;
     252              :   int ret;
     253              : 
     254           12 :   GNUNET_assert (GNUNET_OK ==
     255              :                  GNUNET_CRYPTO_ecdh_eddsa (&contract_priv->ecdhe_priv,
     256              :                                            &purse_pub->eddsa_pub,
     257              :                                            &key));
     258           12 :   cstr = json_dumps (contract_terms,
     259              :                      JSON_COMPACT | JSON_SORT_KEYS);
     260           12 :   clen = strlen (cstr);
     261           12 :   cbuf_size = compressBound (clen);
     262           12 :   xbuf = GNUNET_malloc (cbuf_size);
     263           12 :   ret = compress (xbuf,
     264              :                   &cbuf_size,
     265              :                   (const Bytef *) cstr,
     266              :                   clen);
     267           12 :   GNUNET_assert (Z_OK == ret);
     268           12 :   free (cstr);
     269           12 :   hdr = GNUNET_malloc (sizeof (*hdr) + cbuf_size);
     270           12 :   hdr->header.ctype = htonl (TALER_EXCHANGE_CONTRACT_PAYMENT_OFFER);
     271           12 :   hdr->header.clen = htonl ((uint32_t) clen);
     272           12 :   hdr->merge_priv = *merge_priv;
     273           12 :   GNUNET_memcpy (&hdr[1],
     274              :                  xbuf,
     275              :                  cbuf_size);
     276           12 :   GNUNET_free (xbuf);
     277           12 :   GNUNET_CRYPTO_random_block (&nonce,
     278              :                               sizeof (nonce));
     279           12 :   blob_encrypt (&nonce,
     280              :                 &key,
     281              :                 sizeof (key),
     282              :                 hdr,
     283              :                 sizeof (*hdr) + cbuf_size,
     284              :                 MERGE_SALT,
     285              :                 econtract,
     286              :                 econtract_size);
     287           12 :   GNUNET_free (hdr);
     288           12 : }
     289              : 
     290              : 
     291              : json_t *
     292            4 : TALER_CRYPTO_contract_decrypt_for_merge (
     293              :   const struct TALER_ContractDiffiePrivateP *contract_priv,
     294              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
     295              :   const void *econtract,
     296              :   size_t econtract_size,
     297              :   struct TALER_PurseMergePrivateKeyP *merge_priv)
     298              : {
     299              :   struct GNUNET_HashCode key;
     300              :   void *xhdr;
     301              :   size_t hdr_size;
     302              :   const struct ContractHeaderMergeP *hdr;
     303              :   char *cstr;
     304              :   uLongf clen;
     305              :   json_error_t json_error;
     306              :   json_t *ret;
     307              : 
     308            4 :   if (GNUNET_OK !=
     309            4 :       GNUNET_CRYPTO_ecdh_eddsa (&contract_priv->ecdhe_priv,
     310              :                                 &purse_pub->eddsa_pub,
     311              :                                 &key))
     312              :   {
     313            0 :     GNUNET_break (0);
     314            0 :     return NULL;
     315              :   }
     316            4 :   if (GNUNET_OK !=
     317            4 :       blob_decrypt (&key,
     318              :                     sizeof (key),
     319              :                     econtract,
     320              :                     econtract_size,
     321              :                     MERGE_SALT,
     322              :                     &xhdr,
     323              :                     &hdr_size))
     324              :   {
     325            0 :     GNUNET_break_op (0);
     326            0 :     return NULL;
     327              :   }
     328            4 :   if (hdr_size < sizeof (*hdr))
     329              :   {
     330            0 :     GNUNET_break_op (0);
     331            0 :     GNUNET_free (xhdr);
     332            0 :     return NULL;
     333              :   }
     334            4 :   hdr = xhdr;
     335            4 :   if (TALER_EXCHANGE_CONTRACT_PAYMENT_OFFER != ntohl (hdr->header.ctype))
     336              :   {
     337            0 :     GNUNET_break_op (0);
     338            0 :     GNUNET_free (xhdr);
     339            0 :     return NULL;
     340              :   }
     341            4 :   clen = ntohl (hdr->header.clen);
     342            4 :   if (clen >= GNUNET_MAX_MALLOC_CHECKED)
     343              :   {
     344            0 :     GNUNET_break_op (0);
     345            0 :     GNUNET_free (xhdr);
     346            0 :     return NULL;
     347              :   }
     348            4 :   cstr = GNUNET_malloc (clen + 1);
     349            4 :   if (Z_OK !=
     350            4 :       uncompress ((Bytef *) cstr,
     351              :                   &clen,
     352            4 :                   (const Bytef *) &hdr[1],
     353              :                   hdr_size - sizeof (*hdr)))
     354              :   {
     355            0 :     GNUNET_break_op (0);
     356            0 :     GNUNET_free (cstr);
     357            0 :     GNUNET_free (xhdr);
     358            0 :     return NULL;
     359              :   }
     360            4 :   *merge_priv = hdr->merge_priv;
     361            4 :   GNUNET_free (xhdr);
     362            4 :   ret = json_loadb ((char *) cstr,
     363              :                     clen,
     364              :                     JSON_DECODE_ANY,
     365              :                     &json_error);
     366            4 :   if (NULL == ret)
     367              :   {
     368            0 :     GNUNET_break_op (0);
     369            0 :     GNUNET_free (cstr);
     370            0 :     return NULL;
     371              :   }
     372            4 :   GNUNET_free (cstr);
     373            4 :   return ret;
     374              : }
     375              : 
     376              : 
     377              : /**
     378              :  * Salt we use when encrypting contracts for merge.
     379              :  */
     380              : #define DEPOSIT_SALT "p2p-deposit-contract"
     381              : 
     382              : 
     383              : void
     384           14 : TALER_CRYPTO_contract_encrypt_for_deposit (
     385              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
     386              :   const struct TALER_ContractDiffiePrivateP *contract_priv,
     387              :   const json_t *contract_terms,
     388              :   void **econtract,
     389              :   size_t *econtract_size)
     390              : {
     391              :   struct GNUNET_HashCode key;
     392              :   char *cstr;
     393              :   size_t clen;
     394              :   void *xbuf;
     395              :   struct ContractHeaderP *hdr;
     396              :   struct NonceP nonce;
     397              :   uLongf cbuf_size;
     398              :   int ret;
     399              :   void *xecontract;
     400              :   size_t xecontract_size;
     401              : 
     402           14 :   GNUNET_assert (GNUNET_OK ==
     403              :                  GNUNET_CRYPTO_ecdh_eddsa (&contract_priv->ecdhe_priv,
     404              :                                            &purse_pub->eddsa_pub,
     405              :                                            &key));
     406           14 :   cstr = json_dumps (contract_terms,
     407              :                      JSON_COMPACT | JSON_SORT_KEYS);
     408           14 :   GNUNET_assert (NULL != cstr);
     409           14 :   clen = strlen (cstr);
     410           14 :   cbuf_size = compressBound (clen);
     411           14 :   xbuf = GNUNET_malloc (cbuf_size);
     412           14 :   ret = compress (xbuf,
     413              :                   &cbuf_size,
     414              :                   (const Bytef *) cstr,
     415              :                   clen);
     416           14 :   GNUNET_assert (Z_OK == ret);
     417           14 :   free (cstr);
     418           14 :   hdr = GNUNET_malloc (sizeof (*hdr) + cbuf_size);
     419           14 :   hdr->ctype = htonl (TALER_EXCHANGE_CONTRACT_PAYMENT_REQUEST);
     420           14 :   hdr->clen = htonl ((uint32_t) clen);
     421           14 :   GNUNET_memcpy (&hdr[1],
     422              :                  xbuf,
     423              :                  cbuf_size);
     424           14 :   GNUNET_free (xbuf);
     425           14 :   GNUNET_CRYPTO_random_block (&nonce,
     426              :                               sizeof (nonce));
     427           14 :   blob_encrypt (&nonce,
     428              :                 &key,
     429              :                 sizeof (key),
     430              :                 hdr,
     431              :                 sizeof (*hdr) + cbuf_size,
     432              :                 DEPOSIT_SALT,
     433              :                 &xecontract,
     434              :                 &xecontract_size);
     435           14 :   GNUNET_free (hdr);
     436              :   /* prepend purse_pub */
     437           14 :   *econtract = GNUNET_malloc (xecontract_size + sizeof (*purse_pub));
     438           14 :   GNUNET_memcpy (*econtract,
     439              :                  purse_pub,
     440              :                  sizeof (*purse_pub));
     441           14 :   GNUNET_memcpy (sizeof (*purse_pub) + *econtract,
     442              :                  xecontract,
     443              :                  xecontract_size);
     444           14 :   *econtract_size = xecontract_size + sizeof (*purse_pub);
     445           14 :   GNUNET_free (xecontract);
     446           14 : }
     447              : 
     448              : 
     449              : json_t *
     450            3 : TALER_CRYPTO_contract_decrypt_for_deposit (
     451              :   const struct TALER_ContractDiffiePrivateP *contract_priv,
     452              :   const void *econtract,
     453              :   size_t econtract_size)
     454              : {
     455            3 :   const struct TALER_PurseContractPublicKeyP *purse_pub = econtract;
     456              :   struct GNUNET_HashCode key;
     457              :   void *xhdr;
     458              :   size_t hdr_size;
     459              :   const struct ContractHeaderP *hdr;
     460              :   char *cstr;
     461              :   uLongf clen;
     462              :   json_error_t json_error;
     463              :   json_t *ret;
     464              : 
     465            3 :   if (econtract_size < sizeof (*purse_pub))
     466              :   {
     467            0 :     GNUNET_break_op (0);
     468            0 :     return NULL;
     469              :   }
     470            3 :   if (GNUNET_OK !=
     471            3 :       GNUNET_CRYPTO_ecdh_eddsa (&contract_priv->ecdhe_priv,
     472              :                                 &purse_pub->eddsa_pub,
     473              :                                 &key))
     474              :   {
     475            0 :     GNUNET_break (0);
     476            0 :     return NULL;
     477              :   }
     478            3 :   econtract += sizeof (*purse_pub);
     479            3 :   econtract_size -= sizeof (*purse_pub);
     480            3 :   if (GNUNET_OK !=
     481            3 :       blob_decrypt (&key,
     482              :                     sizeof (key),
     483              :                     econtract,
     484              :                     econtract_size,
     485              :                     DEPOSIT_SALT,
     486              :                     &xhdr,
     487              :                     &hdr_size))
     488              :   {
     489            0 :     GNUNET_break_op (0);
     490            0 :     return NULL;
     491              :   }
     492            3 :   if (hdr_size < sizeof (*hdr))
     493              :   {
     494            0 :     GNUNET_break_op (0);
     495            0 :     GNUNET_free (xhdr);
     496            0 :     return NULL;
     497              :   }
     498            3 :   hdr = xhdr;
     499            3 :   if (TALER_EXCHANGE_CONTRACT_PAYMENT_REQUEST != ntohl (hdr->ctype))
     500              :   {
     501            0 :     GNUNET_break_op (0);
     502            0 :     GNUNET_free (xhdr);
     503            0 :     return NULL;
     504              :   }
     505            3 :   clen = ntohl (hdr->clen);
     506            3 :   if (clen >= GNUNET_MAX_MALLOC_CHECKED)
     507              :   {
     508            0 :     GNUNET_break_op (0);
     509            0 :     GNUNET_free (xhdr);
     510            0 :     return NULL;
     511              :   }
     512            3 :   cstr = GNUNET_malloc (clen + 1);
     513            3 :   if (Z_OK !=
     514            3 :       uncompress ((Bytef *) cstr,
     515              :                   &clen,
     516            3 :                   (const Bytef *) &hdr[1],
     517              :                   hdr_size - sizeof (*hdr)))
     518              :   {
     519            0 :     GNUNET_break_op (0);
     520            0 :     GNUNET_free (cstr);
     521            0 :     GNUNET_free (xhdr);
     522            0 :     return NULL;
     523              :   }
     524            3 :   GNUNET_free (xhdr);
     525            3 :   ret = json_loadb ((char *) cstr,
     526              :                     clen,
     527              :                     JSON_DECODE_ANY,
     528              :                     &json_error);
     529            3 :   if (NULL == ret)
     530              :   {
     531            0 :     GNUNET_break_op (0);
     532            0 :     GNUNET_free (cstr);
     533            0 :     return NULL;
     534              :   }
     535            3 :   GNUNET_free (cstr);
     536            3 :   return ret;
     537              : }
     538              : 
     539              : 
     540              : /**
     541              :  * Salt we use when encrypting KYC attributes.
     542              :  */
     543              : #define ATTRIBUTE_SALT "kyc-attributes"
     544              : 
     545              : 
     546              : void
     547           14 : TALER_CRYPTO_kyc_attributes_encrypt (
     548              :   const struct TALER_AttributeEncryptionKeyP *key,
     549              :   const json_t *attr,
     550              :   void **enc_attr,
     551              :   size_t *enc_attr_size)
     552              : {
     553              :   uLongf cbuf_size;
     554              :   char *cstr;
     555              :   uLongf clen;
     556              :   void *xbuf;
     557              :   int ret;
     558              :   uint32_t belen;
     559              :   struct NonceP nonce;
     560              : 
     561           14 :   cstr = json_dumps (attr,
     562              :                      JSON_COMPACT | JSON_SORT_KEYS);
     563           14 :   GNUNET_assert (NULL != cstr);
     564           14 :   clen = strlen (cstr);
     565           14 :   GNUNET_assert (clen <= UINT32_MAX);
     566           14 :   cbuf_size = compressBound (clen);
     567           14 :   xbuf = GNUNET_malloc (cbuf_size + sizeof (uint32_t));
     568           14 :   belen = htonl ((uint32_t) clen);
     569           14 :   GNUNET_memcpy (xbuf,
     570              :                  &belen,
     571              :                  sizeof (belen));
     572           14 :   ret = compress (xbuf + 4,
     573              :                   &cbuf_size,
     574              :                   (const Bytef *) cstr,
     575              :                   clen);
     576           14 :   GNUNET_assert (Z_OK == ret);
     577           14 :   free (cstr);
     578           14 :   GNUNET_CRYPTO_random_block (&nonce,
     579              :                               sizeof (nonce));
     580           14 :   blob_encrypt (&nonce,
     581              :                 key,
     582              :                 sizeof (*key),
     583              :                 xbuf,
     584              :                 cbuf_size + sizeof (uint32_t),
     585              :                 ATTRIBUTE_SALT,
     586              :                 enc_attr,
     587              :                 enc_attr_size);
     588           14 :   GNUNET_free (xbuf);
     589           14 : }
     590              : 
     591              : 
     592              : json_t *
     593           28 : TALER_CRYPTO_kyc_attributes_decrypt (
     594              :   const struct TALER_AttributeEncryptionKeyP *key,
     595              :   const void *enc_attr,
     596              :   size_t enc_attr_size)
     597              : {
     598              :   void *xhdr;
     599              :   size_t hdr_size;
     600              :   char *cstr;
     601              :   uLongf clen;
     602              :   json_error_t json_error;
     603              :   json_t *ret;
     604              :   uint32_t belen;
     605              : 
     606           28 :   if (GNUNET_OK !=
     607           28 :       blob_decrypt (key,
     608              :                     sizeof (*key),
     609              :                     enc_attr,
     610              :                     enc_attr_size,
     611              :                     ATTRIBUTE_SALT,
     612              :                     &xhdr,
     613              :                     &hdr_size))
     614              :   {
     615            0 :     GNUNET_break_op (0);
     616            0 :     return NULL;
     617              :   }
     618           28 :   if (hdr_size < sizeof (uint32_t))
     619              :   {
     620            0 :     GNUNET_break_op (0);
     621            0 :     GNUNET_free (xhdr);
     622            0 :     return NULL;
     623              :   }
     624           28 :   GNUNET_memcpy (&belen,
     625              :                  xhdr,
     626              :                  sizeof (belen));
     627           28 :   clen = ntohl (belen);
     628           28 :   if (clen >= GNUNET_MAX_MALLOC_CHECKED)
     629              :   {
     630            0 :     GNUNET_break_op (0);
     631            0 :     GNUNET_free (xhdr);
     632            0 :     return NULL;
     633              :   }
     634           28 :   cstr = GNUNET_malloc (clen + 1);
     635           28 :   if (Z_OK !=
     636           28 :       uncompress ((Bytef *) cstr,
     637              :                   &clen,
     638           28 :                   (const Bytef *) (xhdr + sizeof (uint32_t)),
     639              :                   hdr_size - sizeof (uint32_t)))
     640              :   {
     641            0 :     GNUNET_break_op (0);
     642            0 :     GNUNET_free (cstr);
     643            0 :     GNUNET_free (xhdr);
     644            0 :     return NULL;
     645              :   }
     646           28 :   GNUNET_free (xhdr);
     647           28 :   ret = json_loadb ((char *) cstr,
     648              :                     clen,
     649              :                     JSON_DECODE_ANY,
     650              :                     &json_error);
     651           28 :   if (NULL == ret)
     652              :   {
     653            0 :     GNUNET_break_op (0);
     654            0 :     GNUNET_free (cstr);
     655            0 :     return NULL;
     656              :   }
     657           28 :   GNUNET_free (cstr);
     658           28 :   return ret;
     659              : }
        

Generated by: LCOV version 2.0-1