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