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