anastasis

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

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