LCOV - code coverage report
Current view: top level - lib/crypt_ops - crypto_ed25519.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 227 235 96.6 %
Date: 2021-11-24 03:28:48 Functions: 31 31 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2013-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file crypto_ed25519.c
       6             :  *
       7             :  * \brief Wrapper code for an ed25519 implementation.
       8             :  *
       9             :  * Ed25519 is a Schnorr signature on a Twisted Edwards curve, defined
      10             :  * by Dan Bernstein. For more information, see https://ed25519.cr.yp.to/
      11             :  *
      12             :  * This module wraps our choice of Ed25519 backend, and provides a few
      13             :  * convenience functions for checking and generating signatures.  It also
      14             :  * provides Tor-specific tools for key blinding and for converting Ed25519
      15             :  * keys to and from the corresponding Curve25519 keys.
      16             :  */
      17             : 
      18             : #define CRYPTO_ED25519_PRIVATE
      19             : #include "orconfig.h"
      20             : #ifdef HAVE_SYS_STAT_H
      21             : #include <sys/stat.h>
      22             : #endif
      23             : 
      24             : #include "lib/ctime/di_ops.h"
      25             : #include "lib/crypt_ops/crypto_curve25519.h"
      26             : #include "lib/crypt_ops/crypto_digest.h"
      27             : #include "lib/crypt_ops/crypto_ed25519.h"
      28             : #include "lib/crypt_ops/crypto_format.h"
      29             : #include "lib/crypt_ops/crypto_rand.h"
      30             : #include "lib/crypt_ops/crypto_util.h"
      31             : #include "lib/log/log.h"
      32             : #include "lib/log/util_bug.h"
      33             : #include "lib/encoding/binascii.h"
      34             : #include "lib/string/util_string.h"
      35             : 
      36             : #include "ed25519/ref10/ed25519_ref10.h"
      37             : #include "ed25519/donna/ed25519_donna_tor.h"
      38             : 
      39             : #include <string.h>
      40             : #include <errno.h>
      41             : 
      42             : static void pick_ed25519_impl(void);
      43             : 
      44             : /** An Ed25519 implementation, as a set of function pointers. */
      45             : typedef struct {
      46             :   int (*selftest)(void);
      47             : 
      48             :   int (*seckey)(unsigned char *);
      49             :   int (*seckey_expand)(unsigned char *, const unsigned char *);
      50             :   int (*pubkey)(unsigned char *, const unsigned char *);
      51             :   int (*keygen)(unsigned char *, unsigned char *);
      52             : 
      53             :   int (*open)(const unsigned char *, const unsigned char *, size_t, const
      54             :               unsigned char *);
      55             :   int (*sign)(unsigned char *, const unsigned char *, size_t,
      56             :               const unsigned char *, const unsigned char *);
      57             :   int (*open_batch)(const unsigned char **, size_t *, const unsigned char **,
      58             :                     const unsigned char **, size_t, int *);
      59             : 
      60             :   int (*blind_secret_key)(unsigned char *, const unsigned char *,
      61             :                           const unsigned char *);
      62             :   int (*blind_public_key)(unsigned char *, const unsigned char *,
      63             :                           const unsigned char *);
      64             : 
      65             :   int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
      66             :                                        int);
      67             : 
      68             :   int (*ed25519_scalarmult_with_group_order)(unsigned char *,
      69             :                                              const unsigned char *);
      70             : } ed25519_impl_t;
      71             : 
      72             : /** The Ref10 Ed25519 implementation. This one is pure C and lightly
      73             :  * optimized. */
      74             : static const ed25519_impl_t impl_ref10 = {
      75             :   NULL,
      76             : 
      77             :   ed25519_ref10_seckey,
      78             :   ed25519_ref10_seckey_expand,
      79             :   ed25519_ref10_pubkey,
      80             :   ed25519_ref10_keygen,
      81             : 
      82             :   ed25519_ref10_open,
      83             :   ed25519_ref10_sign,
      84             :   NULL,
      85             : 
      86             :   ed25519_ref10_blind_secret_key,
      87             :   ed25519_ref10_blind_public_key,
      88             : 
      89             :   ed25519_ref10_pubkey_from_curve25519_pubkey,
      90             :   ed25519_ref10_scalarmult_with_group_order,
      91             : };
      92             : 
      93             : /** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
      94             :  * mostly C. The C still tends to be heavily platform-specific. */
      95             : static const ed25519_impl_t impl_donna = {
      96             :   ed25519_donna_selftest,
      97             : 
      98             :   ed25519_donna_seckey,
      99             :   ed25519_donna_seckey_expand,
     100             :   ed25519_donna_pubkey,
     101             :   ed25519_donna_keygen,
     102             : 
     103             :   ed25519_donna_open,
     104             :   ed25519_donna_sign,
     105             :   ed25519_sign_open_batch_donna,
     106             : 
     107             :   ed25519_donna_blind_secret_key,
     108             :   ed25519_donna_blind_public_key,
     109             : 
     110             :   ed25519_donna_pubkey_from_curve25519_pubkey,
     111             :   ed25519_donna_scalarmult_with_group_order,
     112             : };
     113             : 
     114             : /** Which Ed25519 implementation are we using?  NULL if we haven't decided
     115             :  * yet. */
     116             : static const ed25519_impl_t *ed25519_impl = NULL;
     117             : 
     118             : /** Helper: Return our chosen Ed25519 implementation.
     119             :  *
     120             :  * This should only be called after we've picked an implementation, but
     121             :  * it _does_ recover if you forget this.
     122             :  **/
     123             : static inline const ed25519_impl_t *
     124       41431 : get_ed_impl(void)
     125             : {
     126       41431 :   if (BUG(ed25519_impl == NULL)) {
     127             :     pick_ed25519_impl(); // LCOV_EXCL_LINE - We always call ed25519_init().
     128             :   }
     129       41431 :   return ed25519_impl;
     130             : }
     131             : 
     132             : #ifdef TOR_UNIT_TESTS
     133             : /** For testing: used to remember our actual choice of Ed25519
     134             :  * implementation */
     135             : static const ed25519_impl_t *saved_ed25519_impl = NULL;
     136             : /** For testing: Use the Ed25519 implementation called <b>name</b> until
     137             :  * crypto_ed25519_testing_restore_impl is called.  Recognized names are
     138             :  * "donna" and "ref10". */
     139             : void
     140          18 : crypto_ed25519_testing_force_impl(const char *name)
     141             : {
     142          18 :   tor_assert(saved_ed25519_impl == NULL);
     143          18 :   saved_ed25519_impl = ed25519_impl;
     144          18 :   if (! strcmp(name, "donna")) {
     145           9 :     ed25519_impl = &impl_donna;
     146             :   } else {
     147           9 :     tor_assert(!strcmp(name, "ref10"));
     148           9 :     ed25519_impl = &impl_ref10;
     149             :   }
     150          18 : }
     151             : /** For testing: go back to whatever Ed25519 implementation we had picked
     152             :  * before crypto_ed25519_testing_force_impl was called.
     153             :  */
     154             : void
     155          18 : crypto_ed25519_testing_restore_impl(void)
     156             : {
     157          18 :   ed25519_impl = saved_ed25519_impl;
     158          18 :   saved_ed25519_impl = NULL;
     159          18 : }
     160             : #endif /* defined(TOR_UNIT_TESTS) */
     161             : 
     162             : /**
     163             :  * Initialize a new ed25519 secret key in <b>seckey_out</b>.  If
     164             :  * <b>extra_strong</b>, take the RNG inputs directly from the operating
     165             :  * system.  Return 0 on success, -1 on failure.
     166             :  */
     167             : int
     168        2564 : ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
     169             :                         int extra_strong)
     170             : {
     171        2564 :   int r;
     172        2564 :   uint8_t seed[32];
     173        2564 :   if (extra_strong)
     174        1058 :     crypto_strongest_rand(seed, sizeof(seed));
     175             :  else
     176        1506 :     crypto_rand((char*)seed, sizeof(seed));
     177             : 
     178        2564 :   r = get_ed_impl()->seckey_expand(seckey_out->seckey, seed);
     179        2564 :   memwipe(seed, 0, sizeof(seed));
     180             : 
     181        2564 :   return r < 0 ? -1 : 0;
     182             : }
     183             : 
     184             : /**
     185             :  * Given a 32-byte random seed in <b>seed</b>, expand it into an ed25519
     186             :  * secret key in <b>seckey_out</b>.  Return 0 on success, -1 on failure.
     187             :  */
     188             : int
     189          57 : ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
     190             :                              const uint8_t *seed)
     191             : {
     192          57 :   if (get_ed_impl()->seckey_expand(seckey_out->seckey, seed) < 0)
     193           0 :      return -1;
     194             :   return 0;
     195             : }
     196             : 
     197             : /**
     198             :  * Given a secret key in <b>seckey</b>, expand it into an
     199             :  * ed25519 public key.  Return 0 on success, -1 on failure.
     200             :  */
     201             : int
     202        9164 : ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
     203             :                         const ed25519_secret_key_t *seckey)
     204             : {
     205        9164 :   if (get_ed_impl()->pubkey(pubkey_out->pubkey, seckey->seckey) < 0)
     206           0 :     return -1;
     207             :   return 0;
     208             : }
     209             : 
     210             : /** Generate a new ed25519 keypair in <b>keypair_out</b>.  If
     211             :  * <b>extra_strong</b> is set, try to mix some system entropy into the key
     212             :  * generation process. Return 0 on success, -1 on failure. */
     213             : int
     214        2519 : ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong)
     215             : {
     216        2519 :   if (ed25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
     217             :     return -1;
     218        2519 :   if (ed25519_public_key_generate(&keypair_out->pubkey,
     219             :                                   &keypair_out->seckey)<0)
     220           0 :     return -1;
     221             :   return 0;
     222             : }
     223             : 
     224             : /** Return true iff 'pubkey' is set to zero (eg to indicate that it is not
     225             :  * set). */
     226             : int
     227       42917 : ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
     228             : {
     229       42917 :   return safe_mem_is_zero((char*)pubkey->pubkey, ED25519_PUBKEY_LEN);
     230             : }
     231             : 
     232             : /* Return a heap-allocated array that contains <b>msg</b> prefixed by the
     233             :  * string <b>prefix_str</b>. Set <b>final_msg_len_out</b> to the size of the
     234             :  * final array. If an error occurred, return NULL. It's the responsibility of
     235             :  * the caller to free the returned array. */
     236             : static uint8_t *
     237         186 : get_prefixed_msg(const uint8_t *msg, size_t msg_len,
     238             :                  const char *prefix_str,
     239             :                  size_t *final_msg_len_out)
     240             : {
     241         186 :   size_t prefixed_msg_len, prefix_len;
     242         186 :   uint8_t *prefixed_msg;
     243             : 
     244         186 :   tor_assert(prefix_str);
     245         186 :   tor_assert(final_msg_len_out);
     246             : 
     247         186 :   prefix_len = strlen(prefix_str);
     248             : 
     249             :   /* msg_len + strlen(prefix_str) must not overflow. */
     250         186 :   if (msg_len > SIZE_T_CEILING - prefix_len) {
     251             :     return NULL;
     252             :   }
     253             : 
     254         186 :   prefixed_msg_len = msg_len + prefix_len;
     255         186 :   prefixed_msg = tor_malloc_zero(prefixed_msg_len);
     256             : 
     257         186 :   memcpy(prefixed_msg, prefix_str, prefix_len);
     258         186 :   memcpy(prefixed_msg + prefix_len, msg, msg_len);
     259             : 
     260         186 :   *final_msg_len_out = prefixed_msg_len;
     261         186 :   return prefixed_msg;
     262             : }
     263             : 
     264             : /**
     265             :  * Set <b>signature_out</b> to a signature of the <b>len</b>-byte message
     266             :  * <b>msg</b>, using the secret and public key in <b>keypair</b>.
     267             :  *
     268             :  * Return 0 if we successfully signed the message, otherwise return -1.
     269             :  */
     270             : int
     271        4873 : ed25519_sign(ed25519_signature_t *signature_out,
     272             :              const uint8_t *msg, size_t len,
     273             :              const ed25519_keypair_t *keypair)
     274             : {
     275        9746 :   if (get_ed_impl()->sign(signature_out->sig, msg, len,
     276        4873 :                           keypair->seckey.seckey,
     277        4873 :                           keypair->pubkey.pubkey) < 0) {
     278           0 :     return -1;
     279             :   }
     280             : 
     281             :   return 0;
     282             : }
     283             : 
     284             : /**
     285             :  * Like ed25519_sign(), but also prefix <b>msg</b> with <b>prefix_str</b>
     286             :  * before signing. <b>prefix_str</b> must be a NUL-terminated string.
     287             :  */
     288          77 : MOCK_IMPL(int,
     289             : ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
     290             :                        const uint8_t *msg, size_t msg_len,
     291             :                        const char *prefix_str,
     292             :                        const ed25519_keypair_t *keypair))
     293             : {
     294          77 :   int retval;
     295          77 :   size_t prefixed_msg_len;
     296          77 :   uint8_t *prefixed_msg;
     297             : 
     298          77 :   tor_assert(prefix_str);
     299             : 
     300          77 :   prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
     301             :                                   &prefixed_msg_len);
     302          77 :   if (BUG(!prefixed_msg)) {
     303             :     /* LCOV_EXCL_START -- only possible when the message and prefix are
     304             :      * ridiculously huge */
     305             :     log_warn(LD_GENERAL, "Failed to get prefixed msg.");
     306             :     return -1;
     307             :     /* LCOV_EXCL_STOP */
     308             :   }
     309             : 
     310          77 :   retval = ed25519_sign(signature_out,
     311             :                         prefixed_msg, prefixed_msg_len,
     312             :                         keypair);
     313          77 :   tor_free(prefixed_msg);
     314             : 
     315          77 :   return retval;
     316             : }
     317             : 
     318             : /**
     319             :  * Check whether if <b>signature</b> is a valid signature for the
     320             :  * <b>len</b>-byte message in <b>msg</b> made with the key <b>pubkey</b>.
     321             :  *
     322             :  * Return 0 if the signature is valid; -1 if it isn't.
     323             :  */
     324        6640 : MOCK_IMPL(int,
     325             : ed25519_checksig,(const ed25519_signature_t *signature,
     326             :                   const uint8_t *msg, size_t len,
     327             :                   const ed25519_public_key_t *pubkey))
     328             : {
     329        6640 :   return
     330        6640 :     get_ed_impl()->open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0;
     331             : }
     332             : 
     333             : /**
     334             :  * Like ed2519_checksig(), but also prefix <b>msg</b> with <b>prefix_str</b>
     335             :  * before verifying signature. <b>prefix_str</b> must be a NUL-terminated
     336             :  * string.
     337             :  */
     338             : int
     339         109 : ed25519_checksig_prefixed(const ed25519_signature_t *signature,
     340             :                           const uint8_t *msg, size_t msg_len,
     341             :                           const char *prefix_str,
     342             :                           const ed25519_public_key_t *pubkey)
     343             : {
     344         109 :   int retval;
     345         109 :   size_t prefixed_msg_len;
     346         109 :   uint8_t *prefixed_msg;
     347             : 
     348         109 :   prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
     349             :                                   &prefixed_msg_len);
     350         109 :   if (BUG(!prefixed_msg)) {
     351             :     /* LCOV_EXCL_START -- only possible when the message and prefix are
     352             :      * ridiculously huge */
     353             :     log_warn(LD_GENERAL, "Failed to get prefixed msg.");
     354             :     return -1;
     355             :     /* LCOV_EXCL_STOP */
     356             :   }
     357             : 
     358         109 :   retval = ed25519_checksig(signature,
     359             :                             prefixed_msg, prefixed_msg_len,
     360             :                             pubkey);
     361         109 :   tor_free(prefixed_msg);
     362             : 
     363         109 :   return retval;
     364             : }
     365             : 
     366             : /** Validate every signature among those in <b>checkable</b>, which contains
     367             :  * exactly <b>n_checkable</b> elements.  If <b>okay_out</b> is non-NULL, set
     368             :  * the i'th element of <b>okay_out</b> to 1 if the i'th element of
     369             :  * <b>checkable</b> is valid, and to 0 otherwise.  Return 0 if every signature
     370             :  * was valid. Otherwise return -N, where N is the number of invalid
     371             :  * signatures.
     372             :  */
     373        1326 : MOCK_IMPL(int,
     374             : ed25519_checksig_batch,(int *okay_out,
     375             :                         const ed25519_checkable_t *checkable,
     376             :                         int n_checkable))
     377             : {
     378        1326 :   int i, res;
     379        1326 :   const ed25519_impl_t *impl = get_ed_impl();
     380             : 
     381        1326 :   if (impl->open_batch == NULL) {
     382             :     /* No batch verification implementation available, fake it by checking the
     383             :      * each signature individually.
     384             :      */
     385             :     res = 0;
     386          16 :     for (i = 0; i < n_checkable; ++i) {
     387          12 :       const ed25519_checkable_t *ch = &checkable[i];
     388          12 :       int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
     389          12 :       if (r < 0)
     390           4 :         --res;
     391          12 :       if (okay_out)
     392           6 :         okay_out[i] = (r == 0);
     393             :     }
     394             :   } else {
     395             :     /* ed25519-donna style batch verification available.
     396             :      *
     397             :      * Theoretically, this should only be called if n_checkable >= 3, since
     398             :      * that's the threshold where the batch verification actually kicks in,
     399             :      * but the only difference is a few mallocs/frees.
     400             :      */
     401        1322 :     const uint8_t **ms;
     402        1322 :     size_t *lens;
     403        1322 :     const uint8_t **pks;
     404        1322 :     const uint8_t **sigs;
     405        1322 :     int *oks;
     406        1322 :     int all_ok;
     407             : 
     408        1322 :     ms = tor_calloc(n_checkable, sizeof(uint8_t*));
     409        1322 :     lens = tor_calloc(n_checkable, sizeof(size_t));
     410        1322 :     pks = tor_calloc(n_checkable, sizeof(uint8_t*));
     411        1322 :     sigs = tor_calloc(n_checkable, sizeof(uint8_t*));
     412        1322 :     oks = okay_out ? okay_out : tor_calloc(n_checkable, sizeof(int));
     413             : 
     414        2830 :     for (i = 0; i < n_checkable; ++i) {
     415        1508 :       ms[i] = checkable[i].msg;
     416        1508 :       lens[i] = checkable[i].len;
     417        1508 :       pks[i] = checkable[i].pubkey->pubkey;
     418        1508 :       sigs[i] = checkable[i].signature.sig;
     419        1508 :       oks[i] = 0;
     420             :     }
     421             : 
     422        1322 :     res = 0;
     423        1322 :     all_ok = impl->open_batch(ms, lens, pks, sigs, n_checkable, oks);
     424        4152 :     for (i = 0; i < n_checkable; ++i) {
     425        1508 :       if (!oks[i])
     426          10 :         --res;
     427             :     }
     428             :     /* XXX: For now sanity check oks with the return value.  Once we have
     429             :      * more confidence in the code, if `all_ok == 0` we can skip iterating
     430             :      * over oks since all the signatures were found to be valid.
     431             :      */
     432        1322 :     tor_assert(((res == 0) && !all_ok) || ((res < 0) && all_ok));
     433             : 
     434        1322 :     tor_free(ms);
     435        1322 :     tor_free(lens);
     436        1322 :     tor_free(pks);
     437        1322 :     tor_free(sigs);
     438        1322 :     if (! okay_out)
     439           7 :       tor_free(oks);
     440             :   }
     441             : 
     442        1326 :   return res;
     443             : }
     444             : 
     445             : /**
     446             :  * Given a curve25519 keypair in <b>inp</b>, generate a corresponding
     447             :  * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the
     448             :  * sign bit of the X coordinate of the ed25519 key.
     449             :  *
     450             :  * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING
     451             :  * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228.  In particular, it's probably
     452             :  * not a great idea to use it to sign attacker-supplied anything.
     453             :  */
     454             : int
     455        2243 : ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
     456             :                                         int *signbit_out,
     457             :                                         const curve25519_keypair_t *inp)
     458             : {
     459        2243 :   const char string[] = "Derive high part of ed25519 key from curve25519 key";
     460        2243 :   ed25519_public_key_t pubkey_check;
     461        2243 :   crypto_digest_t *ctx;
     462        2243 :   uint8_t sha512_output[DIGEST512_LEN];
     463             : 
     464        2243 :   memcpy(out->seckey.seckey, inp->seckey.secret_key, 32);
     465             : 
     466        2243 :   ctx = crypto_digest512_new(DIGEST_SHA512);
     467        2243 :   crypto_digest_add_bytes(ctx, (const char*)out->seckey.seckey, 32);
     468        2243 :   crypto_digest_add_bytes(ctx, (const char*)string, sizeof(string));
     469        2243 :   crypto_digest_get_digest(ctx, (char *)sha512_output, sizeof(sha512_output));
     470        2243 :   crypto_digest_free(ctx);
     471        2243 :   memcpy(out->seckey.seckey + 32, sha512_output, 32);
     472             : 
     473        2243 :   ed25519_public_key_generate(&out->pubkey, &out->seckey);
     474             : 
     475        2243 :   *signbit_out = out->pubkey.pubkey[31] >> 7;
     476             : 
     477        2243 :   ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey,
     478             :                                                 *signbit_out);
     479             : 
     480        2243 :   tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
     481             : 
     482        2243 :   memwipe(&pubkey_check, 0, sizeof(pubkey_check));
     483        2243 :   memwipe(sha512_output, 0, sizeof(sha512_output));
     484             : 
     485        2243 :   return 0;
     486             : }
     487             : 
     488             : /**
     489             :  * Given a curve25519 public key and sign bit of X coordinate of the ed25519
     490             :  * public key, generate the corresponding ed25519 public key.
     491             :  */
     492             : int
     493        4473 : ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
     494             :                                      const curve25519_public_key_t *pubkey_in,
     495             :                                      int signbit)
     496             : {
     497        4473 :   return get_ed_impl()->pubkey_from_curve25519_pubkey(pubkey->pubkey,
     498        4473 :                                                       pubkey_in->public_key,
     499             :                                                       signbit);
     500             : }
     501             : 
     502             : /**
     503             :  * Given an ed25519 keypair in <b>inp</b>, generate a corresponding
     504             :  * ed25519 keypair in <b>out</b>, blinded by the corresponding 32-byte input
     505             :  * in 'param'.
     506             :  *
     507             :  * Tor uses key blinding for the "next-generation" hidden services design:
     508             :  * service descriptors are encrypted with a key derived from the service's
     509             :  * long-term public key, and then signed with (and stored at a position
     510             :  * indexed by) a short-term key derived by blinding the long-term keys.
     511             :  *
     512             :  * Return 0 if blinding was successful, else return -1. */
     513             : int
     514        2201 : ed25519_keypair_blind(ed25519_keypair_t *out,
     515             :                       const ed25519_keypair_t *inp,
     516             :                       const uint8_t *param)
     517             : {
     518        2201 :   ed25519_public_key_t pubkey_check;
     519             : 
     520        2201 :   get_ed_impl()->blind_secret_key(out->seckey.seckey,
     521        2201 :                                   inp->seckey.seckey, param);
     522             : 
     523        2201 :   if (ed25519_public_blind(&pubkey_check, &inp->pubkey, param) < 0) {
     524             :     return -1;
     525             :   }
     526        2201 :   ed25519_public_key_generate(&out->pubkey, &out->seckey);
     527             : 
     528        2201 :   tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
     529             : 
     530        2201 :   memwipe(&pubkey_check, 0, sizeof(pubkey_check));
     531             : 
     532        2201 :   return 0;
     533             : }
     534             : 
     535             : /**
     536             :  * Given an ed25519 public key in <b>inp</b>, generate a corresponding blinded
     537             :  * public key in <b>out</b>, blinded with the 32-byte parameter in
     538             :  * <b>param</b>.  Return 0 on success, -1 on railure.
     539             :  */
     540             : int
     541        4423 : ed25519_public_blind(ed25519_public_key_t *out,
     542             :                      const ed25519_public_key_t *inp,
     543             :                      const uint8_t *param)
     544             : {
     545        4423 :   return get_ed_impl()->blind_public_key(out->pubkey, inp->pubkey, param);
     546             : }
     547             : 
     548             : /**
     549             :  * Store seckey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
     550             :  * Return 0 on success, -1 on failure.
     551             :  */
     552             : int
     553          30 : ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
     554             :                              const char *filename,
     555             :                              const char *tag)
     556             : {
     557          60 :   return crypto_write_tagged_contents_to_file(filename,
     558             :                                               "ed25519v1-secret",
     559             :                                               tag,
     560          30 :                                               seckey->seckey,
     561             :                                               sizeof(seckey->seckey));
     562             : }
     563             : 
     564             : /**
     565             :  * Read seckey unencrypted from <b>filename</b>, storing it into
     566             :  * <b>seckey_out</b>.  Set *<b>tag_out</b> to the tag it was marked with.
     567             :  * Return 0 on success, -1 on failure.
     568             :  */
     569             : int
     570         107 : ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
     571             :                               char **tag_out,
     572             :                               const char *filename)
     573             : {
     574         107 :   ssize_t len;
     575             : 
     576         214 :   len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-secret",
     577         107 :                                               tag_out, seckey_out->seckey,
     578             :                                               sizeof(seckey_out->seckey));
     579         107 :   if (len == sizeof(seckey_out->seckey)) {
     580             :     return 0;
     581          59 :   } else if (len >= 0) {
     582           1 :     errno = EINVAL;
     583             :   }
     584             : 
     585          59 :   tor_free(*tag_out);
     586          59 :   return -1;
     587             : }
     588             : 
     589             : /**
     590             :  * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
     591             :  * Return 0 on success, -1 on failure.
     592             :  */
     593             : int
     594          16 : ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
     595             :                              const char *filename,
     596             :                              const char *tag)
     597             : {
     598          32 :   return crypto_write_tagged_contents_to_file(filename,
     599             :                                               "ed25519v1-public",
     600             :                                               tag,
     601          16 :                                               pubkey->pubkey,
     602             :                                               sizeof(pubkey->pubkey));
     603             : }
     604             : 
     605             : /**
     606             :  * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
     607             :  * Return 0 on success, -1 on failure.
     608             :  */
     609             : int
     610          93 : ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
     611             :                               char **tag_out,
     612             :                               const char *filename)
     613             : {
     614          93 :   ssize_t len;
     615             : 
     616         186 :   len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-public",
     617          93 :                                               tag_out, pubkey_out->pubkey,
     618             :                                               sizeof(pubkey_out->pubkey));
     619          93 :   if (len == sizeof(pubkey_out->pubkey)) {
     620             :     return 0;
     621          53 :   } else if (len >= 0) {
     622           1 :     errno = EINVAL;
     623             :   }
     624             : 
     625          53 :   tor_free(*tag_out);
     626          53 :   return -1;
     627             : }
     628             : 
     629             : /** Release all storage held for <b>kp</b>. */
     630             : void
     631        1229 : ed25519_keypair_free_(ed25519_keypair_t *kp)
     632             : {
     633        1229 :   if (! kp)
     634             :     return;
     635             : 
     636         173 :   memwipe(kp, 0, sizeof(*kp));
     637         173 :   tor_free(kp);
     638             : }
     639             : 
     640             : /** Return true iff <b>key1</b> and <b>key2</b> are the same public key. */
     641             : int
     642       16238 : ed25519_pubkey_eq(const ed25519_public_key_t *key1,
     643             :                   const ed25519_public_key_t *key2)
     644             : {
     645       16238 :   tor_assert(key1);
     646       16238 :   tor_assert(key2);
     647       16238 :   return tor_memeq(key1->pubkey, key2->pubkey, ED25519_PUBKEY_LEN);
     648             : }
     649             : 
     650             : /**
     651             :  * Set <b>dest</b> to contain the same key as <b>src</b>.
     652             :  */
     653             : void
     654         357 : ed25519_pubkey_copy(ed25519_public_key_t *dest,
     655             :                     const ed25519_public_key_t *src)
     656             : {
     657         357 :   tor_assert(dest);
     658         357 :   tor_assert(src);
     659         357 :   memcpy(dest, src, sizeof(ed25519_public_key_t));
     660         357 : }
     661             : 
     662             : /** Check whether the given Ed25519 implementation seems to be working.
     663             :  * If so, return 0; otherwise return -1. */
     664        5561 : MOCK_IMPL(STATIC int,
     665             : ed25519_impl_spot_check,(void))
     666             : {
     667        5561 :   static const uint8_t alicesk[32] = {
     668             :     0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,
     669             :     0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,
     670             :     0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,
     671             :     0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7
     672             :   };
     673        5561 :   static const uint8_t alicepk[32] = {
     674             :     0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,
     675             :     0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,
     676             :     0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,
     677             :     0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25
     678             :   };
     679        5561 :   static const uint8_t alicemsg[2] = { 0xaf, 0x82 };
     680        5561 :   static const uint8_t alicesig[64] = {
     681             :     0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,
     682             :     0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,
     683             :     0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,
     684             :     0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,
     685             :     0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,
     686             :     0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,
     687             :     0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,
     688             :     0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a
     689             :   };
     690        5561 :   const ed25519_impl_t *impl = get_ed_impl();
     691        5561 :   uint8_t sk[ED25519_SECKEY_LEN];
     692        5561 :   uint8_t pk[ED25519_PUBKEY_LEN];
     693        5561 :   uint8_t sig[ED25519_SIG_LEN];
     694        5561 :   int r = 0;
     695             : 
     696             :   /* Some implementations (eg: The modified Ed25519-donna) have handy self-test
     697             :    * code that sanity-checks the internals.  If present, use that to screen out
     698             :    * catastrophic errors like massive compiler failure.
     699             :    */
     700        5561 :   if (impl->selftest && impl->selftest() != 0)
     701           0 :     goto fail;
     702             : 
     703             :   /* Validate results versus known answer tests.  People really should be
     704             :    * running "make test" instead of relying on this, but it's better than
     705             :    * nothing.
     706             :    *
     707             :    * Test vectors taken from "EdDSA & Ed25519 - 6. Test Vectors for Ed25519
     708             :    * (TEST3)" (draft-josefsson-eddsa-ed25519-03).
     709             :    */
     710             : 
     711             :   /* Key expansion, public key derivation. */
     712        5561 :   if (impl->seckey_expand(sk, alicesk) < 0)
     713           0 :     goto fail;
     714        5561 :   if (impl->pubkey(pk, sk) < 0)
     715           0 :     goto fail;
     716        5561 :   if (fast_memneq(pk, alicepk, ED25519_PUBKEY_LEN))
     717           0 :     goto fail;
     718             : 
     719             :   /* Signing, verification. */
     720        5561 :   if (impl->sign(sig, alicemsg, sizeof(alicemsg), sk, pk) < 0)
     721             :     return -1;
     722        5561 :   if (fast_memneq(sig, alicesig, ED25519_SIG_LEN))
     723             :     return -1;
     724        5561 :   if (impl->open(sig, alicemsg, sizeof(alicemsg), pk) < 0)
     725             :     return -1;
     726             : 
     727             :   /* XXX/yawning: Someone that's more paranoid than I am, can write "Assume
     728             :    * ref0 is canonical, and fuzz impl against it" if they want, but I doubt
     729             :    * that will catch anything that the known answer tests won't.
     730             :    */
     731        5561 :   goto end;
     732             : 
     733             :  // LCOV_EXCL_START -- We can only reach this if our ed25519 implementation is
     734             :  // broken.
     735             :  fail:
     736             :   r = -1;
     737             :  // LCOV_EXCL_STOP
     738             :  end:
     739             :   return r;
     740             : }
     741             : 
     742             : /** Force the Ed25519 implementation to a given one, without sanity checking
     743             :  * the output.  Used for testing.
     744             :  */
     745             : void
     746        4096 : ed25519_set_impl_params(int use_donna)
     747             : {
     748        4096 :   if (use_donna)
     749        2048 :     ed25519_impl = &impl_donna;
     750             :   else
     751        2048 :     ed25519_impl = &impl_ref10;
     752        4096 : }
     753             : 
     754             : /** Choose whether to use the Ed25519-donna implementation. */
     755             : static void
     756        9558 : pick_ed25519_impl(void)
     757             : {
     758        9558 :   ed25519_impl = &impl_donna;
     759             : 
     760        9558 :   if (ed25519_impl_spot_check() == 0)
     761             :     return;
     762             : 
     763             :   /* LCOV_EXCL_START
     764             :    * unreachable unless ed25519_donna is broken */
     765             :   log_warn(LD_CRYPTO, "The Ed25519-donna implementation seems broken; using "
     766             :            "the ref10 implementation.");
     767             :   ed25519_impl = &impl_ref10;
     768             :   /* LCOV_EXCL_STOP */
     769             : }
     770             : 
     771             : /* Initialize the Ed25519 implementation. This is necessary if you're
     772             :  * going to use them in a multithreaded setting, and not otherwise. */
     773             : void
     774        9558 : ed25519_init(void)
     775             : {
     776        9558 :   pick_ed25519_impl();
     777        9558 : }
     778             : 
     779             : /* Return true if <b>point</b> is the identity element of the ed25519 group. */
     780             : static int
     781         296 : ed25519_point_is_identity_element(const uint8_t *point)
     782             : {
     783             :   /* The identity element in ed25159 is the point with coordinates (0,1). */
     784         296 :   static const uint8_t ed25519_identity[32] = {
     785             :     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     786             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     787             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     788             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
     789         296 :   tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN);
     790         296 :   return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity));
     791             : }
     792             : 
     793             : /** Validate <b>pubkey</b> to ensure that it has no torsion component.
     794             :  *  Return 0 if <b>pubkey</b> is valid, else return -1. */
     795             : int
     796         150 : ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
     797             : {
     798         150 :   uint8_t result[32] = {0};
     799             : 
     800             :   /* First check that we were not given the identity element */
     801         150 :   if (ed25519_point_is_identity_element(pubkey->pubkey)) {
     802           1 :     log_warn(LD_CRYPTO, "ed25519 pubkey is the identity");
     803           1 :     return -1;
     804             :   }
     805             : 
     806             :   /* For any point on the curve, doing l*point should give the identity element
     807             :    * (where l is the group order). Do the computation and check that the
     808             :    * identity element is returned. */
     809         149 :   if (get_ed_impl()->ed25519_scalarmult_with_group_order(result,
     810             :                                                          pubkey->pubkey) < 0) {
     811           3 :     log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed");
     812           3 :     return -1;
     813             :   }
     814             : 
     815         146 :   if (!ed25519_point_is_identity_element(result)) {
     816           6 :     log_warn(LD_CRYPTO, "ed25519 validation failed");
     817           6 :     return -1;
     818             :   }
     819             : 
     820             :   return 0;
     821             : }

Generated by: LCOV version 1.14