LCOV - code coverage report
Current view: top level - util - test_crypto.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.8 % 169 145
Test Date: 2026-01-04 22:17:00 Functions: 100.0 % 9 9

            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 "taler/platform.h"
      23              : #include "taler/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_AgeCommitmentHashP *ach = NULL;
     133            2 :   struct TALER_AgeCommitmentHashP 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_AgeCommitmentHashP *ach = NULL;
     232            2 :   struct TALER_AgeCommitmentHashP 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 2.0-1