anastasis

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

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