anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

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 */