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