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