LCOV - code coverage report
Current view: top level - util - test_crypto.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 145 169 85.8 %
Date: 2025-06-05 21:03:14 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   (C) 2015, 2020-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             : /**
      18             :  * @file util/test_crypto.c
      19             :  * @brief Tests for Taler-specific crypto logic
      20             :  * @author Christian Grothoff <christian@grothoff.org>
      21             :  */
      22             : #include "platform.h"
      23             : #include "taler_util.h"
      24             : 
      25             : 
      26             : /**
      27             :  * Test high-level link encryption/decryption API.
      28             :  *
      29             :  * @return 0 on success
      30             :  */
      31             : static int
      32           1 : test_high_level (void)
      33             : {
      34             :   struct TALER_CoinSpendPrivateKeyP coin_priv;
      35             :   struct TALER_CoinSpendPublicKeyP coin_pub;
      36             :   struct TALER_TransferPrivateKeyP trans_priv;
      37             :   struct TALER_TransferPublicKeyP trans_pub;
      38             :   struct TALER_TransferSecretP secret;
      39             :   struct TALER_TransferSecretP secret2;
      40             :   union GNUNET_CRYPTO_BlindingSecretP bks1;
      41             :   union GNUNET_CRYPTO_BlindingSecretP bks2;
      42             :   struct TALER_CoinSpendPrivateKeyP coin_priv1;
      43             :   struct TALER_CoinSpendPrivateKeyP coin_priv2;
      44             :   struct TALER_PlanchetMasterSecretP ps1;
      45             :   struct TALER_PlanchetMasterSecretP ps2;
      46           1 :   struct GNUNET_CRYPTO_BlindingInputValues bi = {
      47             :     .cipher = GNUNET_CRYPTO_BSA_RSA
      48             :   };
      49           1 :   struct TALER_ExchangeBlindingValues alg1 = {
      50             :     .blinding_inputs = &bi
      51             :   };
      52           1 :   struct TALER_ExchangeBlindingValues alg2 = {
      53             :     .blinding_inputs = &bi
      54             :   };
      55             : 
      56           1 :   GNUNET_CRYPTO_eddsa_key_create (&coin_priv.eddsa_priv);
      57           1 :   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv,
      58             :                                       &coin_pub.eddsa_pub);
      59           1 :   GNUNET_CRYPTO_ecdhe_key_create (&trans_priv.ecdhe_priv);
      60           1 :   GNUNET_CRYPTO_ecdhe_key_get_public (&trans_priv.ecdhe_priv,
      61             :                                       &trans_pub.ecdhe_pub);
      62           1 :   TALER_link_derive_transfer_secret (&coin_priv,
      63             :                                      &trans_priv,
      64             :                                      &secret);
      65           1 :   TALER_link_reveal_transfer_secret (&trans_priv,
      66             :                                      &coin_pub,
      67             :                                      &secret2);
      68           1 :   GNUNET_assert (0 ==
      69             :                  GNUNET_memcmp (&secret,
      70             :                                 &secret2));
      71           1 :   TALER_link_recover_transfer_secret (&trans_pub,
      72             :                                       &coin_priv,
      73             :                                       &secret2);
      74           1 :   GNUNET_assert (0 ==
      75             :                  GNUNET_memcmp (&secret,
      76             :                                 &secret2));
      77           1 :   TALER_transfer_secret_to_planchet_secret (&secret,
      78             :                                             0,
      79             :                                             &ps1);
      80           1 :   TALER_planchet_setup_coin_priv (&ps1,
      81             :                                   &alg1,
      82             :                                   &coin_priv1);
      83           1 :   TALER_planchet_blinding_secret_create (&ps1,
      84             :                                          &alg1,
      85             :                                          &bks1);
      86           1 :   TALER_transfer_secret_to_planchet_secret (&secret,
      87             :                                             1,
      88             :                                             &ps2);
      89           1 :   TALER_planchet_setup_coin_priv (&ps2,
      90             :                                   &alg2,
      91             :                                   &coin_priv2);
      92           1 :   TALER_planchet_blinding_secret_create (&ps2,
      93             :                                          &alg2,
      94             :                                          &bks2);
      95           1 :   GNUNET_assert (0 !=
      96             :                  GNUNET_memcmp (&ps1,
      97             :                                 &ps2));
      98           1 :   GNUNET_assert (0 !=
      99             :                  GNUNET_memcmp (&coin_priv1,
     100             :                                 &coin_priv2));
     101           1 :   GNUNET_assert (0 !=
     102             :                  GNUNET_memcmp (&bks1,
     103             :                                 &bks2));
     104           1 :   return 0;
     105             : }
     106             : 
     107             : 
     108             : static struct TALER_AgeMask age_mask = {
     109             :   .bits = 1 | 1 << 8 | 1 << 10 | 1 << 12
     110             :           | 1 << 14 | 1 << 16 | 1 << 18 | 1 << 21
     111             : };
     112             : 
     113             : /**
     114             :  * Test the basic planchet functionality of creating a fresh planchet
     115             :  * and extracting the respective signature.
     116             :  *
     117             :  * @return 0 on success
     118             :  */
     119             : static int
     120           2 : test_planchets_rsa (uint8_t age)
     121             : {
     122             :   struct TALER_PlanchetMasterSecretP ps;
     123             :   struct TALER_CoinSpendPrivateKeyP coin_priv;
     124             :   union GNUNET_CRYPTO_BlindingSecretP bks;
     125             :   struct TALER_DenominationPrivateKey dk_priv;
     126             :   struct TALER_DenominationPublicKey dk_pub;
     127             :   const struct TALER_ExchangeBlindingValues *alg_values;
     128             :   struct TALER_PlanchetDetail pd;
     129             :   struct TALER_BlindedDenominationSignature blind_sig;
     130             :   struct TALER_FreshCoin coin;
     131             :   struct TALER_CoinPubHashP c_hash;
     132           2 :   struct TALER_AgeCommitmentHash *ach = NULL;
     133           2 :   struct TALER_AgeCommitmentHash ah = {0};
     134             : 
     135           2 :   alg_values = TALER_denom_ewv_rsa_singleton ();
     136           2 :   if (0 < age)
     137             :   {
     138             :     struct TALER_AgeCommitmentProof acp;
     139             :     struct GNUNET_HashCode seed;
     140             : 
     141           1 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     142             :                                 &seed,
     143             :                                 sizeof(seed));
     144           1 :     TALER_age_restriction_commit (&age_mask,
     145             :                                   age,
     146             :                                   &seed,
     147             :                                   &acp);
     148           1 :     TALER_age_commitment_hash (&acp.commitment,
     149             :                                &ah);
     150           1 :     ach = &ah;
     151           1 :     TALER_age_commitment_proof_free (&acp);
     152             :   }
     153             : 
     154           2 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
     155             :                               &ps,
     156             :                               sizeof (ps));
     157           2 :   GNUNET_log_skip (1, GNUNET_YES);
     158           2 :   GNUNET_assert (GNUNET_SYSERR ==
     159             :                  TALER_denom_priv_create (&dk_priv,
     160             :                                           &dk_pub,
     161             :                                           GNUNET_CRYPTO_BSA_INVALID));
     162           2 :   GNUNET_log_skip (1, GNUNET_YES);
     163           2 :   GNUNET_assert (GNUNET_SYSERR ==
     164             :                  TALER_denom_priv_create (&dk_priv,
     165             :                                           &dk_pub,
     166             :                                           42));
     167             : 
     168           2 :   GNUNET_assert (GNUNET_OK ==
     169             :                  TALER_denom_priv_create (&dk_priv,
     170             :                                           &dk_pub,
     171             :                                           GNUNET_CRYPTO_BSA_RSA,
     172             :                                           1024));
     173           2 :   TALER_planchet_setup_coin_priv (&ps,
     174             :                                   alg_values,
     175             :                                   &coin_priv);
     176           2 :   TALER_planchet_blinding_secret_create (&ps,
     177             :                                          alg_values,
     178             :                                          &bks);
     179           2 :   GNUNET_assert (GNUNET_OK ==
     180             :                  TALER_planchet_prepare (&dk_pub,
     181             :                                          alg_values,
     182             :                                          &bks,
     183             :                                          NULL,
     184             :                                          &coin_priv,
     185             :                                          ach,
     186             :                                          &c_hash,
     187             :                                          &pd));
     188           2 :   GNUNET_assert (GNUNET_OK ==
     189             :                  TALER_denom_sign_blinded (&blind_sig,
     190             :                                            &dk_priv,
     191             :                                            false,
     192             :                                            &pd.blinded_planchet));
     193           2 :   TALER_planchet_detail_free (&pd);
     194           2 :   GNUNET_assert (GNUNET_OK ==
     195             :                  TALER_planchet_to_coin (&dk_pub,
     196             :                                          &blind_sig,
     197             :                                          &bks,
     198             :                                          &coin_priv,
     199             :                                          ach,
     200             :                                          &c_hash,
     201             :                                          alg_values,
     202             :                                          &coin));
     203           2 :   TALER_blinded_denom_sig_free (&blind_sig);
     204           2 :   TALER_denom_sig_free (&coin.sig);
     205           2 :   TALER_denom_priv_free (&dk_priv);
     206           2 :   TALER_denom_pub_free (&dk_pub);
     207           2 :   return 0;
     208             : }
     209             : 
     210             : 
     211             : /**
     212             :  * Test the basic planchet functionality of creating a fresh planchet with CS denomination
     213             :  * and extracting the respective signature.
     214             :  *
     215             :  * @return 0 on success
     216             :  */
     217             : static int
     218           2 : test_planchets_cs (uint8_t age)
     219             : {
     220             :   struct TALER_PlanchetMasterSecretP ps;
     221             :   struct TALER_CoinSpendPrivateKeyP coin_priv;
     222             :   union GNUNET_CRYPTO_BlindingSecretP bks;
     223             :   struct TALER_DenominationPrivateKey dk_priv;
     224             :   struct TALER_DenominationPublicKey dk_pub;
     225             :   struct TALER_PlanchetDetail pd;
     226             :   struct TALER_CoinPubHashP c_hash;
     227             :   union GNUNET_CRYPTO_BlindSessionNonce nonce;
     228             :   struct TALER_BlindedDenominationSignature blind_sig;
     229             :   struct TALER_FreshCoin coin;
     230             :   struct TALER_ExchangeBlindingValues alg_values;
     231           2 :   struct TALER_AgeCommitmentHash *ach = NULL;
     232           2 :   struct TALER_AgeCommitmentHash ah = {0};
     233             : 
     234           2 :   if (0 < age)
     235             :   {
     236             :     struct TALER_AgeCommitmentProof acp;
     237             :     struct GNUNET_HashCode seed;
     238             : 
     239           1 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     240             :                                 &seed,
     241             :                                 sizeof(seed));
     242           1 :     TALER_age_restriction_commit (&age_mask,
     243             :                                   age,
     244             :                                   &seed,
     245             :                                   &acp);
     246           1 :     TALER_age_commitment_hash (&acp.commitment,
     247             :                                &ah);
     248           1 :     ach = &ah;
     249           1 :     TALER_age_commitment_proof_free (&acp);
     250             :   }
     251             : 
     252           2 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
     253             :                               &ps,
     254             :                               sizeof (ps));
     255           2 :   GNUNET_assert (GNUNET_OK ==
     256             :                  TALER_denom_priv_create (&dk_priv,
     257             :                                           &dk_pub,
     258             :                                           GNUNET_CRYPTO_BSA_CS));
     259             : #pragma message "phase out TALER_cs_withdraw_nonce_derive"
     260           2 :   TALER_cs_withdraw_nonce_derive (
     261             :     &ps,
     262             :     &nonce.cs_nonce);
     263             :   // FIXME: define Taler abstraction for this:
     264             :   alg_values.blinding_inputs
     265           2 :     = GNUNET_CRYPTO_get_blinding_input_values (dk_priv.bsign_priv_key,
     266             :                                                &nonce,
     267             :                                                "rw");
     268           2 :   TALER_denom_pub_hash (&dk_pub,
     269             :                         &pd.denom_pub_hash);
     270           2 :   TALER_planchet_setup_coin_priv (&ps,
     271             :                                   &alg_values,
     272             :                                   &coin_priv);
     273           2 :   TALER_planchet_blinding_secret_create (&ps,
     274             :                                          &alg_values,
     275             :                                          &bks);
     276           2 :   GNUNET_assert (GNUNET_OK ==
     277             :                  TALER_planchet_prepare (&dk_pub,
     278             :                                          &alg_values,
     279             :                                          &bks,
     280             :                                          &nonce,
     281             :                                          &coin_priv,
     282             :                                          ach,
     283             :                                          &c_hash,
     284             :                                          &pd));
     285           2 :   GNUNET_assert (GNUNET_OK ==
     286             :                  TALER_denom_sign_blinded (&blind_sig,
     287             :                                            &dk_priv,
     288             :                                            false,
     289             :                                            &pd.blinded_planchet));
     290           2 :   GNUNET_assert (GNUNET_OK ==
     291             :                  TALER_planchet_to_coin (&dk_pub,
     292             :                                          &blind_sig,
     293             :                                          &bks,
     294             :                                          &coin_priv,
     295             :                                          ach,
     296             :                                          &c_hash,
     297             :                                          &alg_values,
     298             :                                          &coin));
     299           2 :   TALER_blinded_denom_sig_free (&blind_sig);
     300           2 :   TALER_denom_sig_free (&coin.sig);
     301           2 :   TALER_denom_priv_free (&dk_priv);
     302           2 :   TALER_denom_pub_free (&dk_pub);
     303           2 :   return 0;
     304             : }
     305             : 
     306             : 
     307             : /**
     308             :  * Test the basic planchet functionality of creating a fresh planchet
     309             :  * and extracting the respective signature.
     310             :  * Calls test_planchets_rsa and test_planchets_cs
     311             :  *
     312             :  * @return 0 on success
     313             :  */
     314             : static int
     315           2 : test_planchets (uint8_t age)
     316             : {
     317           2 :   if (0 != test_planchets_rsa (age))
     318           0 :     return -1;
     319           2 :   return test_planchets_cs (age);
     320             : }
     321             : 
     322             : 
     323             : static int
     324           1 : test_exchange_sigs (void)
     325             : {
     326           1 :   const struct TALER_FullPayto pt = {
     327             :     .full_payto
     328             :       = (char *) "payto://x-taler-bank/localhost/Account?receiver-name=ACC"
     329             :   };
     330           1 :   const struct TALER_FullPayto pto = {
     331             :     .full_payto
     332             :       = (char *) "payto://x-taler-bank/localhost/Other?receiver-name=OTH"
     333             :   };
     334             :   struct TALER_MasterPrivateKeyP priv;
     335             :   struct TALER_MasterPublicKeyP pub;
     336             :   struct TALER_MasterSignatureP sig;
     337             :   json_t *rest;
     338             : 
     339           1 :   GNUNET_CRYPTO_eddsa_key_create (&priv.eddsa_priv);
     340           1 :   rest = json_array ();
     341           1 :   GNUNET_assert (NULL != rest);
     342           1 :   TALER_exchange_wire_signature_make (pt,
     343             :                                       NULL,
     344             :                                       rest,
     345             :                                       rest,
     346             :                                       &priv,
     347             :                                       &sig);
     348           1 :   GNUNET_CRYPTO_eddsa_key_get_public (&priv.eddsa_priv,
     349             :                                       &pub.eddsa_pub);
     350           1 :   if (GNUNET_OK !=
     351           1 :       TALER_exchange_wire_signature_check (pt,
     352             :                                            NULL,
     353             :                                            rest,
     354             :                                            rest,
     355             :                                            &pub,
     356             :                                            &sig))
     357             :   {
     358           0 :     GNUNET_break (0);
     359           0 :     return 1;
     360             :   }
     361           1 :   if (GNUNET_OK ==
     362           1 :       TALER_exchange_wire_signature_check (
     363             :         pto,
     364             :         NULL,
     365             :         rest,
     366             :         rest,
     367             :         &pub,
     368             :         &sig))
     369             :   {
     370           0 :     GNUNET_break (0);
     371           0 :     return 1;
     372             :   }
     373           1 :   if (GNUNET_OK ==
     374           1 :       TALER_exchange_wire_signature_check (
     375             :         pt,
     376             :         "http://example.com/",
     377             :         rest,
     378             :         rest,
     379             :         &pub,
     380             :         &sig))
     381             :   {
     382           0 :     GNUNET_break (0);
     383           0 :     return 1;
     384             :   }
     385           1 :   json_decref (rest);
     386           1 :   return 0;
     387             : }
     388             : 
     389             : 
     390             : static int
     391           1 : test_merchant_sigs (void)
     392             : {
     393           1 :   const struct TALER_FullPayto pt = {
     394             :     .full_payto
     395             :       = (char *) "payto://x-taler-bank/localhost/Account?receiver-name=ACC"
     396             :   };
     397           1 :   const struct TALER_FullPayto pto = {
     398             :     .full_payto
     399             :       = (char *) "payto://x-taler-bank/localhost/Other?receiver-name=OTH"
     400             :   };
     401             :   struct TALER_WireSaltP salt;
     402             :   struct TALER_MerchantPrivateKeyP priv;
     403             :   struct TALER_MerchantPublicKeyP pub;
     404             :   struct TALER_MerchantSignatureP sig;
     405             : 
     406           1 :   GNUNET_CRYPTO_eddsa_key_create (&priv.eddsa_priv);
     407           1 :   memset (&salt,
     408             :           42,
     409             :           sizeof (salt));
     410           1 :   TALER_merchant_wire_signature_make (pt,
     411             :                                       &salt,
     412             :                                       &priv,
     413             :                                       &sig);
     414           1 :   GNUNET_CRYPTO_eddsa_key_get_public (&priv.eddsa_priv,
     415             :                                       &pub.eddsa_pub);
     416           1 :   if (GNUNET_OK !=
     417           1 :       TALER_merchant_wire_signature_check (pt,
     418             :                                            &salt,
     419             :                                            &pub,
     420             :                                            &sig))
     421             :   {
     422           0 :     GNUNET_break (0);
     423           0 :     return 1;
     424             :   }
     425           1 :   if (GNUNET_OK ==
     426           1 :       TALER_merchant_wire_signature_check (
     427             :         pto,
     428             :         &salt,
     429             :         &pub,
     430             :         &sig))
     431             :   {
     432           0 :     GNUNET_break (0);
     433           0 :     return 1;
     434             :   }
     435           1 :   memset (&salt,
     436             :           43,
     437             :           sizeof (salt));
     438           1 :   if (GNUNET_OK ==
     439           1 :       TALER_merchant_wire_signature_check (pt,
     440             :                                            &salt,
     441             :                                            &pub,
     442             :                                            &sig))
     443             :   {
     444           0 :     GNUNET_break (0);
     445           0 :     return 1;
     446             :   }
     447           1 :   return 0;
     448             : }
     449             : 
     450             : 
     451             : static int
     452           1 : test_contracts (void)
     453             : {
     454             :   struct TALER_ContractDiffiePrivateP cpriv;
     455             :   struct TALER_PurseContractPublicKeyP purse_pub;
     456             :   struct TALER_PurseContractPrivateKeyP purse_priv;
     457             :   void *econtract;
     458             :   size_t econtract_size;
     459             :   struct TALER_PurseMergePrivateKeyP mpriv_in;
     460             :   struct TALER_PurseMergePrivateKeyP mpriv_out;
     461             :   json_t *c;
     462             : 
     463           1 :   GNUNET_CRYPTO_ecdhe_key_create (&cpriv.ecdhe_priv);
     464           1 :   GNUNET_CRYPTO_eddsa_key_create (&purse_priv.eddsa_priv);
     465           1 :   GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv.eddsa_priv,
     466             :                                       &purse_pub.eddsa_pub);
     467           1 :   memset (&mpriv_in,
     468             :           42,
     469             :           sizeof (mpriv_in));
     470           1 :   c = json_pack ("{s:s}", "test", "value");
     471           1 :   GNUNET_assert (NULL != c);
     472           1 :   TALER_CRYPTO_contract_encrypt_for_merge (&purse_pub,
     473             :                                            &cpriv,
     474             :                                            &mpriv_in,
     475             :                                            c,
     476             :                                            &econtract,
     477             :                                            &econtract_size);
     478           1 :   json_decref (c);
     479           1 :   c = TALER_CRYPTO_contract_decrypt_for_merge (&cpriv,
     480             :                                                &purse_pub,
     481             :                                                econtract,
     482             :                                                econtract_size,
     483             :                                                &mpriv_out);
     484           1 :   GNUNET_free (econtract);
     485           1 :   if (NULL == c)
     486           0 :     return 1;
     487           1 :   json_decref (c);
     488           1 :   if (0 != GNUNET_memcmp (&mpriv_in,
     489             :                           &mpriv_out))
     490           0 :     return 1;
     491           1 :   return 0;
     492             : }
     493             : 
     494             : 
     495             : static int
     496           1 : test_attributes (void)
     497             : {
     498             :   struct TALER_AttributeEncryptionKeyP key;
     499             :   void *eattr;
     500             :   size_t eattr_size;
     501             :   json_t *c;
     502             : 
     503           1 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     504             :                               &key,
     505             :                               sizeof (key));
     506           1 :   c = json_pack ("{s:s}", "test", "value");
     507           1 :   GNUNET_assert (NULL != c);
     508           1 :   TALER_CRYPTO_kyc_attributes_encrypt (&key,
     509             :                                        c,
     510             :                                        &eattr,
     511             :                                        &eattr_size);
     512           1 :   json_decref (c);
     513           1 :   c = TALER_CRYPTO_kyc_attributes_decrypt (&key,
     514             :                                            eattr,
     515             :                                            eattr_size);
     516           1 :   GNUNET_free (eattr);
     517           1 :   if (NULL == c)
     518             :   {
     519           0 :     GNUNET_break (0);
     520           0 :     return 1;
     521             :   }
     522           1 :   GNUNET_assert (0 ==
     523             :                  strcmp ("value",
     524             :                          json_string_value (json_object_get (c,
     525             :                                                              "test"))));
     526           1 :   json_decref (c);
     527           1 :   return 0;
     528             : }
     529             : 
     530             : 
     531             : int
     532           1 : main (int argc,
     533             :       const char *const argv[])
     534             : {
     535             :   (void) argc;
     536             :   (void) argv;
     537           1 :   GNUNET_log_setup ("test-crypto",
     538             :                     "WARNING",
     539             :                     NULL);
     540           1 :   if (0 != test_high_level ())
     541           0 :     return 1;
     542           1 :   if (0 != test_planchets (0))
     543           0 :     return 2;
     544           1 :   if (0 != test_planchets (13))
     545           0 :     return 3;
     546           1 :   if (0 != test_exchange_sigs ())
     547           0 :     return 4;
     548           1 :   if (0 != test_merchant_sigs ())
     549           0 :     return 5;
     550           1 :   if (0 != test_contracts ())
     551           0 :     return 6;
     552           1 :   if (0 != test_attributes ())
     553           0 :     return 7;
     554           1 :   return 0;
     555             : }
     556             : 
     557             : 
     558             : /* end of test_crypto.c */

Generated by: LCOV version 1.16