anastasis_crypto.c (19061B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2020 Anastasis SARL 4 5 Anastasis 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 Anastasis 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 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file util/anastasis_crypto.c 18 * @brief anastasis crypto api 19 * @author Christian Grothoff 20 * @author Dominik Meister 21 * @author Dennis Neufeld 22 */ 23 #include "platform.h" 24 #include "anastasis_crypto_lib.h" 25 #include <gcrypt.h> 26 #include <taler/taler_json_lib.h> 27 #include <gnunet/gnunet_util_lib.h> 28 #include <string.h> 29 30 31 void 32 ANASTASIS_hash_answer (uint64_t code, 33 struct GNUNET_HashCode *hashed_code) 34 { 35 char cbuf[40]; 36 37 GNUNET_snprintf (cbuf, 38 sizeof (cbuf), 39 "%llu", 40 (unsigned long long) code); 41 GNUNET_CRYPTO_hash (cbuf, 42 strlen (cbuf), 43 hashed_code); 44 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 45 "Hashed answer to %s\n", 46 GNUNET_h2s (hashed_code)); 47 } 48 49 50 void 51 ANASTASIS_CRYPTO_secure_answer_hash ( 52 const char *answer, 53 const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid, 54 const struct ANASTASIS_CRYPTO_QuestionSaltP *salt, 55 struct GNUNET_HashCode *result) 56 { 57 struct GNUNET_HashCode pow; 58 59 GNUNET_CRYPTO_pow_hash (&salt->pow_salt, 60 answer, 61 strlen (answer), 62 &pow); 63 GNUNET_assert (GNUNET_YES == 64 GNUNET_CRYPTO_hkdf_gnunet ( 65 result, 66 sizeof (*result), 67 /* salt / XTS */ 68 uuid, 69 sizeof (*uuid), 70 /* skm */ 71 &pow, 72 sizeof (pow), 73 GNUNET_CRYPTO_kdf_arg_string ( 74 "anastasis-secure-question-hashing"))); 75 } 76 77 78 /** 79 * Compute @a key. 80 * 81 * @param key_material key for calculation 82 * @param key_m_len length of key 83 * @param nonce nonce for calculation 84 * @param salt salt value for calculation 85 * @param[out] key where to write the en-/description key 86 */ 87 static void 88 derive_key (const void *key_material, 89 size_t key_m_len, 90 const struct ANASTASIS_CRYPTO_NonceP *nonce, 91 const char *salt, 92 struct ANASTASIS_CRYPTO_SymKeyP *key) 93 { 94 GNUNET_assert (GNUNET_YES == 95 GNUNET_CRYPTO_hkdf_gnunet ( 96 key, 97 sizeof (*key), 98 /* salt / XTS */ 99 nonce, 100 sizeof (*nonce), 101 /* ikm */ 102 key_material, 103 key_m_len, 104 /* info chunks */ 105 /* The "salt" passed here is actually not something random, 106 but a protocol-specific identifier string. Thus 107 we pass it as a context info to the HKDF */ 108 GNUNET_CRYPTO_kdf_arg_string (salt))); 109 } 110 111 112 /** 113 * Encryption of data like recovery document etc. 114 * 115 * @param nonce value to use for the nonce 116 * @param key key which is used to derive a key/iv pair from 117 * @param key_len length of key 118 * @param data data to encrypt 119 * @param data_size size of the data 120 * @param salt salt value which is used for key derivation 121 * @param[out] res ciphertext output 122 * @param[out] res_size size of the ciphertext 123 */ 124 static void 125 anastasis_encrypt (const struct ANASTASIS_CRYPTO_NonceP *nonce, 126 const void *key, 127 size_t key_len, 128 const void *data, 129 size_t data_size, 130 const char *salt, 131 void **res, 132 size_t *res_size) 133 { 134 size_t ciphertext_size; 135 struct ANASTASIS_CRYPTO_SymKeyP skey; 136 137 derive_key (key, 138 key_len, 139 nonce, 140 salt, 141 &skey); 142 ciphertext_size = crypto_secretbox_NONCEBYTES 143 + crypto_secretbox_MACBYTES + data_size; 144 *res_size = ciphertext_size; 145 *res = GNUNET_malloc (ciphertext_size); 146 memcpy (*res, nonce, crypto_secretbox_NONCEBYTES); 147 GNUNET_assert (0 == 148 crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES, 149 data, 150 data_size, 151 (void *) nonce, 152 (void *) &skey)); 153 } 154 155 156 /** 157 * Decryption of data like encrypted recovery document etc. 158 * 159 * @param key key which is used to derive a key/iv pair from 160 * @param key_len length of key 161 * @param data data to decrypt 162 * @param data_size size of the data 163 * @param salt salt value which is used for key derivation 164 * @param[out] res plaintext output 165 * @param[out] res_size size of the plaintext 166 * @return #GNUNET_OK on success 167 */ 168 static enum GNUNET_GenericReturnValue 169 anastasis_decrypt (const void *key, 170 size_t key_len, 171 const void *data, 172 size_t data_size, 173 const char *salt, 174 void **res, 175 size_t *res_size) 176 { 177 const struct ANASTASIS_CRYPTO_NonceP *nonce; 178 struct ANASTASIS_CRYPTO_SymKeyP skey; 179 size_t plaintext_size; 180 181 if (data_size < crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES) 182 { 183 /* short ciphertext is what a hostile provider sends, not a local bug */ 184 GNUNET_break_op (0); 185 *res = NULL; 186 *res_size = 0; 187 return GNUNET_SYSERR; 188 } 189 nonce = data; 190 derive_key (key, 191 key_len, 192 nonce, 193 salt, 194 &skey); 195 plaintext_size = data_size - (crypto_secretbox_NONCEBYTES 196 + crypto_secretbox_MACBYTES); 197 *res = GNUNET_malloc (plaintext_size); 198 *res_size = plaintext_size; 199 if (0 != crypto_secretbox_open_easy (*res, 200 data + crypto_secretbox_NONCEBYTES, 201 data_size - crypto_secretbox_NONCEBYTES, 202 (void *) nonce, 203 (void *) &skey)) 204 { 205 /* likewise: a wrong answer or a hostile provider, not a local bug */ 206 GNUNET_break_op (0); 207 GNUNET_free (*res); 208 *res = NULL; 209 *res_size = 0; 210 return GNUNET_SYSERR; 211 } 212 return GNUNET_OK; 213 } 214 215 216 void 217 ANASTASIS_CRYPTO_user_identifier_derive ( 218 const json_t *id_data, 219 const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt, 220 struct ANASTASIS_CRYPTO_UserIdentifierP *id) 221 { 222 char *json_enc; 223 struct GNUNET_HashCode hash; 224 225 json_enc = json_dumps (id_data, 226 JSON_COMPACT | JSON_SORT_KEYS); 227 GNUNET_assert (NULL != json_enc); 228 GNUNET_CRYPTO_pow_hash (&provider_salt->salt, 229 json_enc, 230 strlen (json_enc), 231 &hash); 232 id->hash = hash; 233 free (json_enc); 234 } 235 236 237 void 238 ANASTASIS_CRYPTO_account_private_key_derive ( 239 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 240 struct ANASTASIS_CRYPTO_AccountPrivateKeyP *priv_key) 241 { 242 /* priv_key = ver_secret */ 243 GNUNET_assert (GNUNET_YES == 244 GNUNET_CRYPTO_hkdf_gnunet ( 245 &priv_key->priv, 246 sizeof (priv_key->priv), 247 /* salt / XTS */ 248 NULL, 249 0, 250 /* ikm */ 251 id, 252 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), 253 /* context chunks */ 254 GNUNET_CRYPTO_kdf_arg_string ("ver"))); 255 } 256 257 258 void 259 ANASTASIS_CRYPTO_account_public_key_derive ( 260 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 261 struct ANASTASIS_CRYPTO_AccountPublicKeyP *pub_key) 262 { 263 struct ANASTASIS_CRYPTO_AccountPrivateKeyP priv; 264 265 ANASTASIS_CRYPTO_account_private_key_derive (id, 266 &priv); 267 GNUNET_CRYPTO_eddsa_key_get_public (&priv.priv, 268 &pub_key->pub); 269 } 270 271 272 void 273 ANASTASIS_CRYPTO_recovery_document_encrypt ( 274 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 275 const void *rec_doc, 276 size_t rd_size, 277 void **enc_rec_doc, 278 size_t *erd_size) 279 { 280 const char *salt = "erd"; 281 struct ANASTASIS_CRYPTO_NonceP nonce; 282 283 GNUNET_CRYPTO_random_block (&nonce, 284 sizeof (nonce)); 285 anastasis_encrypt (&nonce, 286 id, 287 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), 288 rec_doc, 289 rd_size, 290 salt, 291 enc_rec_doc, 292 erd_size); 293 } 294 295 296 enum GNUNET_GenericReturnValue 297 ANASTASIS_CRYPTO_recovery_document_decrypt ( 298 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 299 const void *enc_rec_doc, 300 size_t erd_size, 301 void **rec_doc, 302 size_t *rd_size) 303 { 304 const char *salt = "erd"; 305 306 return anastasis_decrypt (id, 307 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), 308 enc_rec_doc, 309 erd_size, 310 salt, 311 rec_doc, 312 rd_size); 313 } 314 315 316 void 317 ANASTASIS_CRYPTO_keyshare_encrypt ( 318 const struct ANASTASIS_CRYPTO_KeyShareP *key_share, 319 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 320 const char *xsalt, 321 struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share) 322 { 323 const char *salt = "eks"; 324 size_t eks_size = 0; 325 void *eks = NULL; 326 struct ANASTASIS_CRYPTO_NonceP nonce; 327 328 GNUNET_CRYPTO_random_block (&nonce, 329 sizeof (nonce)); 330 anastasis_encrypt (&nonce, 331 id, 332 sizeof (*id), 333 key_share, 334 sizeof (*key_share), 335 (NULL == xsalt) ? salt : xsalt, 336 &eks, 337 &eks_size); 338 GNUNET_assert (eks_size == 339 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); 340 memcpy (enc_key_share, 341 eks, 342 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); 343 GNUNET_free (eks); 344 } 345 346 347 enum GNUNET_GenericReturnValue 348 ANASTASIS_CRYPTO_keyshare_decrypt ( 349 const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share, 350 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 351 const char *xsalt, 352 struct ANASTASIS_CRYPTO_KeyShareP *key_share) 353 { 354 const char *salt = "eks"; 355 size_t ks_size = 0; 356 void *ks = NULL; 357 358 if (GNUNET_OK != 359 anastasis_decrypt (id, 360 sizeof (*id), 361 enc_key_share, 362 sizeof (*enc_key_share), 363 (NULL == xsalt) ? salt : xsalt, 364 &ks, 365 &ks_size)) 366 return GNUNET_SYSERR; 367 if (ks_size != 368 sizeof (struct ANASTASIS_CRYPTO_KeyShareP)) 369 { 370 /* the ciphertext came from an untrusted provider, so a wrong 371 plaintext size must not be an assertion */ 372 GNUNET_break_op (0); 373 GNUNET_free (ks); 374 return GNUNET_SYSERR; 375 } 376 memcpy (key_share, 377 ks, 378 sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); 379 GNUNET_free (ks); 380 return GNUNET_OK; 381 } 382 383 384 void 385 ANASTASIS_CRYPTO_truth_encrypt ( 386 const struct ANASTASIS_CRYPTO_NonceP *nonce, 387 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key, 388 const void *truth, 389 size_t truth_size, 390 void **enc_truth, 391 size_t *ect_size) 392 { 393 const char *salt = "ect"; 394 395 anastasis_encrypt (nonce, 396 truth_enc_key, 397 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP), 398 truth, 399 truth_size, 400 salt, 401 enc_truth, 402 ect_size); 403 } 404 405 406 enum GNUNET_GenericReturnValue 407 ANASTASIS_CRYPTO_truth_decrypt ( 408 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key, 409 const void *enc_truth, 410 size_t ect_size, 411 void **truth, 412 size_t *truth_size) 413 { 414 const char *salt = "ect"; 415 416 return anastasis_decrypt (truth_enc_key, 417 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP), 418 enc_truth, 419 ect_size, 420 salt, 421 truth, 422 truth_size); 423 } 424 425 426 void 427 ANASTASIS_CRYPTO_keyshare_create ( 428 struct ANASTASIS_CRYPTO_KeyShareP *key_share) 429 { 430 GNUNET_CRYPTO_random_block (key_share, 431 sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); 432 } 433 434 435 void 436 ANASTASIS_CRYPTO_policy_key_derive ( 437 const struct ANASTASIS_CRYPTO_KeyShareP *key_shares, 438 unsigned int keyshare_length, 439 const struct ANASTASIS_CRYPTO_MasterSaltP *salt, 440 struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key) 441 { 442 GNUNET_assert (GNUNET_YES == 443 GNUNET_CRYPTO_hkdf_gnunet ( 444 policy_key, 445 sizeof (*policy_key), 446 /* salt / XTS */ 447 salt, 448 sizeof (*salt), 449 /* ikm */ 450 key_shares, 451 keyshare_length * sizeof (*key_shares), 452 /* info chunks */ 453 GNUNET_CRYPTO_kdf_arg_string ( 454 "anastasis-policy-key-derive"))); 455 } 456 457 458 struct ANASTASIS_CoreSecretEncryptionResult * 459 ANASTASIS_CRYPTO_core_secret_encrypt ( 460 const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_keys, 461 unsigned int policy_keys_length, 462 const void *core_secret, 463 size_t core_secret_size) 464 { 465 struct GNUNET_HashCode master_key; 466 struct ANASTASIS_CoreSecretEncryptionResult *cser; 467 struct ANASTASIS_CRYPTO_NonceP nonce; 468 469 cser = GNUNET_new (struct ANASTASIS_CoreSecretEncryptionResult); 470 471 GNUNET_CRYPTO_random_block (&master_key, 472 sizeof (struct GNUNET_HashCode)); 473 GNUNET_CRYPTO_random_block (&nonce, 474 sizeof (struct ANASTASIS_CRYPTO_NonceP)); 475 476 anastasis_encrypt (&nonce, 477 &master_key, 478 sizeof (struct GNUNET_HashCode), 479 core_secret, 480 core_secret_size, 481 "cse", 482 &cser->enc_core_secret, 483 &cser->enc_core_secret_size); 484 485 /* Allocate result arrays with NULL-termination so we don't 486 need to store the length to free */ 487 cser->enc_master_key_sizes = GNUNET_new_array (policy_keys_length + 1, 488 size_t); 489 cser->enc_master_keys = GNUNET_new_array (policy_keys_length + 1, 490 void *); 491 492 for (unsigned int i = 0; i < policy_keys_length; i++) 493 { 494 struct ANASTASIS_CRYPTO_NonceP nonce_i; 495 496 GNUNET_CRYPTO_random_block (&nonce_i, 497 sizeof (struct ANASTASIS_CRYPTO_NonceP)); 498 499 anastasis_encrypt (&nonce_i, 500 &policy_keys[i].key, 501 sizeof (struct GNUNET_HashCode), 502 &master_key, 503 sizeof (struct GNUNET_HashCode), 504 "emk", 505 &cser->enc_master_keys[i], 506 &cser->enc_master_key_sizes[i]); 507 } 508 return cser; 509 } 510 511 512 enum GNUNET_GenericReturnValue 513 ANASTASIS_CRYPTO_core_secret_recover ( 514 const void *encrypted_master_key, 515 size_t encrypted_master_key_size, 516 const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key, 517 const void *encrypted_core_secret, 518 size_t encrypted_core_secret_size, 519 void **core_secret, 520 size_t *core_secret_size) 521 { 522 void *master_key; 523 size_t master_key_size; 524 525 *core_secret = NULL; 526 *core_secret_size = 0; 527 if (GNUNET_OK != 528 anastasis_decrypt (&policy_key->key, 529 sizeof (struct GNUNET_HashCode), 530 encrypted_master_key, 531 encrypted_master_key_size, 532 "emk", 533 &master_key, 534 &master_key_size)) 535 { 536 /* the key shares came from providers we do not trust, so failing to 537 reassemble the master key is an expected outcome, not a bug */ 538 GNUNET_break_op (0); 539 return GNUNET_SYSERR; 540 } 541 if (GNUNET_OK != 542 anastasis_decrypt (master_key, 543 master_key_size, 544 encrypted_core_secret, 545 encrypted_core_secret_size, 546 "cse", 547 core_secret, 548 core_secret_size)) 549 { 550 GNUNET_break_op (0); 551 GNUNET_free (master_key); 552 return GNUNET_SYSERR; 553 } 554 GNUNET_free (master_key); 555 /* Deliberately not logged: TALER_b2s() of the core secret is a ~40 bit 556 fingerprint of it, which is enough to confirm a guess for anyone who can 557 read the debug log. */ 558 return GNUNET_OK; 559 } 560 561 562 void 563 ANASTASIS_CRYPTO_destroy_encrypted_core_secret ( 564 struct ANASTASIS_CoreSecretEncryptionResult *cser) 565 { 566 for (unsigned int i = 0; NULL != cser->enc_master_keys[i]; i++) 567 GNUNET_free (cser->enc_master_keys[i]); 568 GNUNET_free (cser->enc_master_keys); 569 GNUNET_free (cser->enc_master_key_sizes); 570 GNUNET_free (cser->enc_core_secret); 571 GNUNET_free (cser); 572 } 573 574 575 const char * 576 ANASTASIS_CRYPTO_uuid2s (const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid) 577 { 578 static char uuids[7]; 579 char *tpk; 580 581 tpk = GNUNET_STRINGS_data_to_string_alloc (uuid, 582 sizeof (*uuid)); 583 memcpy (uuids, 584 tpk, 585 sizeof (uuids) - 1); 586 GNUNET_free (tpk); 587 return uuids; 588 } 589 590 591 void 592 ANASTASIS_CRYPTO_recovery_metadata_encrypt ( 593 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 594 const void *meta_data, 595 size_t meta_data_size, 596 void **enc_meta_data, 597 size_t *enc_meta_data_size) 598 { 599 const char *salt = "rmd"; 600 struct ANASTASIS_CRYPTO_NonceP nonce; 601 602 GNUNET_CRYPTO_random_block (&nonce, 603 sizeof (nonce)); 604 anastasis_encrypt (&nonce, 605 id, 606 sizeof (*id), 607 meta_data, 608 meta_data_size, 609 salt, 610 enc_meta_data, 611 enc_meta_data_size); 612 } 613 614 615 enum GNUNET_GenericReturnValue 616 ANASTASIS_CRYPTO_recovery_metadata_decrypt ( 617 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 618 const void *enc_meta_data, 619 size_t enc_meta_data_size, 620 void **meta_data, 621 size_t *meta_data_size) 622 { 623 const char *salt = "rmd"; 624 625 return anastasis_decrypt (id, 626 sizeof (*id), 627 enc_meta_data, 628 enc_meta_data_size, 629 salt, 630 meta_data, 631 meta_data_size); 632 } 633 634 635 /* end of anastasis_crypto.c */