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