anastasis_crypto.c (18464B)
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 (&nonce, 279 sizeof (nonce)); 280 anastasis_encrypt (&nonce, 281 id, 282 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), 283 rec_doc, 284 rd_size, 285 salt, 286 enc_rec_doc, 287 erd_size); 288 } 289 290 291 void 292 ANASTASIS_CRYPTO_recovery_document_decrypt ( 293 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 294 const void *enc_rec_doc, 295 size_t erd_size, 296 void **rec_doc, 297 size_t *rd_size) 298 { 299 const char *salt = "erd"; 300 301 anastasis_decrypt (id, 302 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), 303 enc_rec_doc, 304 erd_size, 305 salt, 306 rec_doc, 307 rd_size); 308 } 309 310 311 void 312 ANASTASIS_CRYPTO_keyshare_encrypt ( 313 const struct ANASTASIS_CRYPTO_KeyShareP *key_share, 314 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 315 const char *xsalt, 316 struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share) 317 { 318 const char *salt = "eks"; 319 size_t eks_size = 0; 320 void *eks = NULL; 321 struct ANASTASIS_CRYPTO_NonceP nonce; 322 323 GNUNET_CRYPTO_random_block (&nonce, 324 sizeof (nonce)); 325 anastasis_encrypt (&nonce, 326 id, 327 sizeof (*id), 328 key_share, 329 sizeof (*key_share), 330 (NULL == xsalt) ? salt : xsalt, 331 &eks, 332 &eks_size); 333 GNUNET_assert (eks_size == 334 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); 335 memcpy (enc_key_share, 336 eks, 337 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); 338 GNUNET_free (eks); 339 } 340 341 342 void 343 ANASTASIS_CRYPTO_keyshare_decrypt ( 344 const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share, 345 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 346 const char *xsalt, 347 struct ANASTASIS_CRYPTO_KeyShareP *key_share) 348 { 349 const char *salt = "eks"; 350 size_t ks_size = 0; 351 void *ks = NULL; 352 353 anastasis_decrypt (id, 354 sizeof (*id), 355 enc_key_share, 356 sizeof (*enc_key_share), 357 (NULL == xsalt) ? salt : xsalt, 358 &ks, 359 &ks_size); 360 GNUNET_assert (ks_size == 361 sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); 362 memcpy (key_share, 363 ks, 364 sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); 365 GNUNET_free (ks); 366 } 367 368 369 void 370 ANASTASIS_CRYPTO_truth_encrypt ( 371 const struct ANASTASIS_CRYPTO_NonceP *nonce, 372 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key, 373 const void *truth, 374 size_t truth_size, 375 void **enc_truth, 376 size_t *ect_size) 377 { 378 const char *salt = "ect"; 379 380 anastasis_encrypt (nonce, 381 truth_enc_key, 382 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP), 383 truth, 384 truth_size, 385 salt, 386 enc_truth, 387 ect_size); 388 } 389 390 391 void 392 ANASTASIS_CRYPTO_truth_decrypt ( 393 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key, 394 const void *enc_truth, 395 size_t ect_size, 396 void **truth, 397 size_t *truth_size) 398 { 399 const char *salt = "ect"; 400 401 anastasis_decrypt (truth_enc_key, 402 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP), 403 enc_truth, 404 ect_size, 405 salt, 406 truth, 407 truth_size); 408 } 409 410 411 void 412 ANASTASIS_CRYPTO_keyshare_create ( 413 struct ANASTASIS_CRYPTO_KeyShareP *key_share) 414 { 415 GNUNET_CRYPTO_random_block (key_share, 416 sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); 417 } 418 419 420 void 421 ANASTASIS_CRYPTO_policy_key_derive ( 422 const struct ANASTASIS_CRYPTO_KeyShareP *key_shares, 423 unsigned int keyshare_length, 424 const struct ANASTASIS_CRYPTO_MasterSaltP *salt, 425 struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key) 426 { 427 GNUNET_assert (GNUNET_YES == 428 GNUNET_CRYPTO_hkdf_gnunet ( 429 policy_key, 430 sizeof (*policy_key), 431 /* salt / XTS */ 432 salt, 433 sizeof (*salt), 434 /* ikm */ 435 key_shares, 436 keyshare_length * sizeof (*key_shares), 437 /* info chunks */ 438 GNUNET_CRYPTO_kdf_arg_string ( 439 "anastasis-policy-key-derive"))); 440 } 441 442 443 struct ANASTASIS_CoreSecretEncryptionResult * 444 ANASTASIS_CRYPTO_core_secret_encrypt ( 445 const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_keys, 446 unsigned int policy_keys_length, 447 const void *core_secret, 448 size_t core_secret_size) 449 { 450 struct GNUNET_HashCode master_key; 451 struct ANASTASIS_CoreSecretEncryptionResult *cser; 452 struct ANASTASIS_CRYPTO_NonceP nonce; 453 454 cser = GNUNET_new (struct ANASTASIS_CoreSecretEncryptionResult); 455 456 GNUNET_CRYPTO_random_block (&master_key, 457 sizeof (struct GNUNET_HashCode)); 458 GNUNET_CRYPTO_random_block (&nonce, 459 sizeof (struct ANASTASIS_CRYPTO_NonceP)); 460 461 anastasis_encrypt (&nonce, 462 &master_key, 463 sizeof (struct GNUNET_HashCode), 464 core_secret, 465 core_secret_size, 466 "cse", 467 &cser->enc_core_secret, 468 &cser->enc_core_secret_size); 469 470 /* Allocate result arrays with NULL-termination so we don't 471 need to store the length to free */ 472 cser->enc_master_key_sizes = GNUNET_new_array (policy_keys_length + 1, 473 size_t); 474 cser->enc_master_keys = GNUNET_new_array (policy_keys_length + 1, 475 void *); 476 477 for (unsigned int i = 0; i < policy_keys_length; i++) 478 { 479 struct ANASTASIS_CRYPTO_NonceP nonce_i; 480 481 GNUNET_CRYPTO_random_block (&nonce_i, 482 sizeof (struct ANASTASIS_CRYPTO_NonceP)); 483 484 anastasis_encrypt (&nonce_i, 485 &policy_keys[i].key, 486 sizeof (struct GNUNET_HashCode), 487 &master_key, 488 sizeof (struct GNUNET_HashCode), 489 "emk", 490 &cser->enc_master_keys[i], 491 &cser->enc_master_key_sizes[i]); 492 } 493 return cser; 494 } 495 496 497 void 498 ANASTASIS_CRYPTO_core_secret_recover ( 499 const void *encrypted_master_key, 500 size_t encrypted_master_key_size, 501 const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key, 502 const void *encrypted_core_secret, 503 size_t encrypted_core_secret_size, 504 void **core_secret, 505 size_t *core_secret_size) 506 { 507 void *master_key; 508 size_t master_key_size; 509 510 *core_secret = GNUNET_malloc (encrypted_core_secret_size); 511 anastasis_decrypt (&policy_key->key, 512 sizeof (struct GNUNET_HashCode), 513 encrypted_master_key, 514 encrypted_master_key_size, 515 "emk", 516 &master_key, 517 &master_key_size); 518 GNUNET_break (NULL != master_key); 519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 520 "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__, 521 __LINE__, 522 TALER_b2s (encrypted_core_secret, encrypted_core_secret_size), 523 (unsigned long long) encrypted_core_secret_size); 524 anastasis_decrypt (master_key, 525 master_key_size, 526 encrypted_core_secret, 527 encrypted_core_secret_size, 528 "cse", 529 core_secret, 530 core_secret_size); 531 GNUNET_break (NULL != *core_secret); 532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 533 "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__, 534 __LINE__, 535 TALER_b2s (*core_secret, *core_secret_size), 536 (unsigned long long) *core_secret_size); 537 GNUNET_assert (GNUNET_SYSERR != *core_secret_size); 538 } 539 540 541 void 542 ANASTASIS_CRYPTO_destroy_encrypted_core_secret ( 543 struct ANASTASIS_CoreSecretEncryptionResult *cser) 544 { 545 for (unsigned int i = 0; NULL != cser->enc_master_keys[i]; i++) 546 GNUNET_free (cser->enc_master_keys[i]); 547 GNUNET_free (cser->enc_master_keys); 548 GNUNET_free (cser->enc_master_key_sizes); 549 GNUNET_free (cser->enc_core_secret); 550 GNUNET_free (cser); 551 } 552 553 554 const char * 555 ANASTASIS_CRYPTO_uuid2s (const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid) 556 { 557 static char uuids[7]; 558 char *tpk; 559 560 tpk = GNUNET_STRINGS_data_to_string_alloc (uuid, 561 sizeof (*uuid)); 562 memcpy (uuids, 563 tpk, 564 sizeof (uuids) - 1); 565 GNUNET_free (tpk); 566 return uuids; 567 } 568 569 570 void 571 ANASTASIS_CRYPTO_recovery_metadata_encrypt ( 572 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 573 const void *meta_data, 574 size_t meta_data_size, 575 void **enc_meta_data, 576 size_t *enc_meta_data_size) 577 { 578 const char *salt = "rmd"; 579 struct ANASTASIS_CRYPTO_NonceP nonce; 580 581 GNUNET_CRYPTO_random_block (&nonce, 582 sizeof (nonce)); 583 anastasis_encrypt (&nonce, 584 id, 585 sizeof (*id), 586 meta_data, 587 meta_data_size, 588 salt, 589 enc_meta_data, 590 enc_meta_data_size); 591 } 592 593 594 enum GNUNET_GenericReturnValue 595 ANASTASIS_CRYPTO_recovery_metadata_decrypt ( 596 const struct ANASTASIS_CRYPTO_UserIdentifierP *id, 597 const void *enc_meta_data, 598 size_t enc_meta_data_size, 599 void **meta_data, 600 size_t *meta_data_size) 601 { 602 const char *salt = "rmd"; 603 604 return anastasis_decrypt (id, 605 sizeof (*id), 606 enc_meta_data, 607 enc_meta_data_size, 608 salt, 609 meta_data, 610 meta_data_size); 611 } 612 613 614 /* end of anastasis_crypto.c */