tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test_crypto_slow.c (25528B)


      1 /* Copyright (c) 2001-2004, Roger Dingledine.
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 #include "orconfig.h"
      7 #define CRYPTO_S2K_PRIVATE
      8 #include "core/or/or.h"
      9 #include "test/test.h"
     10 #include "ext/equix/include/equix.h"
     11 #include "lib/crypt_ops/crypto_curve25519.h"
     12 #include "lib/crypt_ops/crypto_ed25519.h"
     13 #include "lib/crypt_ops/crypto_s2k.h"
     14 #include "lib/crypt_ops/crypto_pwbox.h"
     15 #include "lib/crypt_ops/crypto_rand.h"
     16 
     17 #if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT)
     18 #define HAVE_LIBSCRYPT
     19 #include <libscrypt.h>
     20 #endif
     21 
     22 #ifdef ENABLE_OPENSSL
     23 #include <openssl/evp.h>
     24 #endif
     25 
     26 /** Run unit tests for our secret-to-key passphrase hashing functionality. */
     27 static void
     28 test_crypto_s2k_rfc2440(void *arg)
     29 {
     30  char buf[29];
     31  char buf2[29];
     32  char *buf3 = NULL;
     33  int i;
     34 
     35  (void)arg;
     36  memset(buf, 0, sizeof(buf));
     37  memset(buf2, 0, sizeof(buf2));
     38  buf3 = tor_malloc(65536);
     39  memset(buf3, 0, 65536);
     40 
     41  secret_to_key_rfc2440(buf+9, 20, "", 0, buf);
     42  crypto_digest(buf2+9, buf3, 1024);
     43  tt_mem_op(buf,OP_EQ, buf2, 29);
     44 
     45  memcpy(buf,"vrbacrda",8);
     46  memcpy(buf2,"vrbacrda",8);
     47  buf[8] = 96;
     48  buf2[8] = 96;
     49  secret_to_key_rfc2440(buf+9, 20, "12345678", 8, buf);
     50  for (i = 0; i < 65536; i += 16) {
     51    memcpy(buf3+i, "vrbacrda12345678", 16);
     52  }
     53  crypto_digest(buf2+9, buf3, 65536);
     54  tt_mem_op(buf,OP_EQ, buf2, 29);
     55 
     56 done:
     57  tor_free(buf3);
     58 }
     59 
     60 static void
     61 run_s2k_tests(const unsigned flags, const unsigned type,
     62              int speclen, const int keylen, int legacy)
     63 {
     64  uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN], buf3[S2K_MAXLEN];
     65  int r;
     66  size_t sz;
     67  const char pw1[] = "You can't come in here unless you say swordfish!";
     68  const char pw2[] = "Now, I give you one more guess.";
     69 
     70  r = secret_to_key_new(buf, sizeof(buf), &sz,
     71                        pw1, strlen(pw1), flags);
     72  tt_int_op(r, OP_EQ, S2K_OKAY);
     73  tt_int_op(buf[0], OP_EQ, type);
     74 
     75  tt_int_op(sz, OP_EQ, keylen + speclen);
     76 
     77  if (legacy) {
     78    memmove(buf, buf+1, sz-1);
     79    --sz;
     80    --speclen;
     81  }
     82 
     83  tt_int_op(S2K_OKAY, OP_EQ,
     84            secret_to_key_check(buf, sz, pw1, strlen(pw1)));
     85 
     86  tt_int_op(S2K_BAD_SECRET, OP_EQ,
     87            secret_to_key_check(buf, sz, pw2, strlen(pw2)));
     88 
     89  /* Move key to buf2, and clear it. */
     90  memset(buf3, 0, sizeof(buf3));
     91  memcpy(buf2, buf+speclen, keylen);
     92  memset(buf+speclen, 0, sz - speclen);
     93 
     94  /* Derivekey should produce the same results. */
     95  tt_int_op(S2K_OKAY, OP_EQ,
     96      secret_to_key_derivekey(buf3, keylen, buf, speclen, pw1, strlen(pw1)));
     97 
     98  tt_mem_op(buf2, OP_EQ, buf3, keylen);
     99 
    100  /* Derivekey with a longer output should fill the output. */
    101  memset(buf2, 0, sizeof(buf2));
    102  tt_int_op(S2K_OKAY, OP_EQ,
    103   secret_to_key_derivekey(buf2, sizeof(buf2), buf, speclen,
    104                           pw1, strlen(pw1)));
    105 
    106  tt_mem_op(buf2, OP_NE, buf3, sizeof(buf2));
    107 
    108  memset(buf3, 0, sizeof(buf3));
    109  tt_int_op(S2K_OKAY, OP_EQ,
    110            secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen,
    111                                    pw1, strlen(pw1)));
    112  tt_mem_op(buf2, OP_EQ, buf3, sizeof(buf3));
    113  tt_assert(!fast_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen));
    114 
    115 done:
    116  ;
    117 }
    118 
    119 static void
    120 test_crypto_s2k_general(void *arg)
    121 {
    122  const char *which = arg;
    123 
    124  if (!strcmp(which, "scrypt")) {
    125    run_s2k_tests(0, 2, 19, 32, 0);
    126  } else if (!strcmp(which, "scrypt-low")) {
    127    run_s2k_tests(S2K_FLAG_LOW_MEM, 2, 19, 32, 0);
    128  } else if (!strcmp(which, "pbkdf2")) {
    129    run_s2k_tests(S2K_FLAG_USE_PBKDF2, 1, 18, 20, 0);
    130  } else if (!strcmp(which, "rfc2440")) {
    131    run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 0);
    132  } else if (!strcmp(which, "rfc2440-legacy")) {
    133    run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 1);
    134  } else {
    135    tt_fail();
    136  }
    137 }
    138 
    139 #if defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT)
    140 static void
    141 test_libscrypt_eq_openssl(void *arg)
    142 {
    143  uint8_t buf1[64];
    144  uint8_t buf2[64];
    145 
    146  uint64_t N;
    147  uint32_t r, p;
    148  uint64_t maxmem = 0; // --> SCRYPT_MAX_MEM in OpenSSL.
    149 
    150  int libscrypt_retval, openssl_retval;
    151 
    152  size_t dk_len = 64;
    153 
    154  (void)arg;
    155 
    156  memset(buf1,0,64);
    157  memset(buf2,0,64);
    158 
    159  /* NOTE: we're using N,r the way OpenSSL and libscrypt define them,
    160   * not the way draft-josefsson-scrypt-kdf-00.txt define them.
    161   */
    162  N = 16;
    163  r = 1;
    164  p = 1;
    165 
    166  libscrypt_retval =
    167  libscrypt_scrypt((const uint8_t *)"", 0, (const uint8_t *)"", 0,
    168                   N, r, p, buf1, dk_len);
    169  openssl_retval =
    170  EVP_PBE_scrypt((const char *)"", 0, (const unsigned char *)"", 0,
    171                  N, r, p, maxmem, buf2, dk_len);
    172 
    173  tt_int_op(libscrypt_retval, OP_EQ, 0);
    174  tt_int_op(openssl_retval, OP_EQ, 1);
    175 
    176  tt_mem_op(buf1, OP_EQ, buf2, 64);
    177 
    178  memset(buf1,0,64);
    179  memset(buf2,0,64);
    180 
    181  N = 1024;
    182  r = 8;
    183  p = 16;
    184 
    185  libscrypt_retval =
    186  libscrypt_scrypt((const uint8_t *)"password", strlen("password"),
    187                   (const uint8_t *)"NaCl", strlen("NaCl"),
    188                   N, r, p, buf1, dk_len);
    189  openssl_retval =
    190  EVP_PBE_scrypt((const char *)"password", strlen("password"),
    191                 (const unsigned char *)"NaCl", strlen("NaCl"),
    192                 N, r, p, maxmem, buf2, dk_len);
    193 
    194  tt_int_op(libscrypt_retval, OP_EQ, 0);
    195  tt_int_op(openssl_retval, OP_EQ, 1);
    196 
    197  tt_mem_op(buf1, OP_EQ, buf2, 64);
    198 
    199  memset(buf1,0,64);
    200  memset(buf2,0,64);
    201 
    202  N = 16384;
    203  r = 8;
    204  p = 1;
    205 
    206  libscrypt_retval =
    207  libscrypt_scrypt((const uint8_t *)"pleaseletmein",
    208                   strlen("pleaseletmein"),
    209                   (const uint8_t *)"SodiumChloride",
    210                   strlen("SodiumChloride"),
    211                   N, r, p, buf1, dk_len);
    212  openssl_retval =
    213  EVP_PBE_scrypt((const char *)"pleaseletmein",
    214                 strlen("pleaseletmein"),
    215                 (const unsigned char *)"SodiumChloride",
    216                 strlen("SodiumChloride"),
    217                 N, r, p, maxmem, buf2, dk_len);
    218 
    219  tt_int_op(libscrypt_retval, OP_EQ, 0);
    220  tt_int_op(openssl_retval, OP_EQ, 1);
    221 
    222  tt_mem_op(buf1, OP_EQ, buf2, 64);
    223 
    224  memset(buf1,0,64);
    225  memset(buf2,0,64);
    226 
    227  N = 1048576;
    228  maxmem = 2 * 1024 * 1024 * (uint64_t)1024; // 2 GB
    229 
    230  libscrypt_retval =
    231  libscrypt_scrypt((const uint8_t *)"pleaseletmein",
    232                   strlen("pleaseletmein"),
    233                   (const uint8_t *)"SodiumChloride",
    234                   strlen("SodiumChloride"),
    235                   N, r, p, buf1, dk_len);
    236  openssl_retval =
    237  EVP_PBE_scrypt((const char *)"pleaseletmein",
    238                 strlen("pleaseletmein"),
    239                 (const unsigned char *)"SodiumChloride",
    240                 strlen("SodiumChloride"),
    241                 N, r, p, maxmem, buf2, dk_len);
    242 
    243  tt_int_op(libscrypt_retval, OP_EQ, 0);
    244  tt_int_op(openssl_retval, OP_EQ, 1);
    245 
    246  tt_mem_op(buf1, OP_EQ, buf2, 64);
    247 
    248  done:
    249  return;
    250 }
    251 #endif /* defined(HAVE_LIBSCRYPT) && defined(HAVE_EVP_PBE_SCRYPT) */
    252 
    253 static void
    254 test_crypto_s2k_errors(void *arg)
    255 {
    256  uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN];
    257  size_t sz;
    258 
    259  (void)arg;
    260 
    261  /* Bogus specifiers: simple */
    262  tt_int_op(S2K_BAD_LEN, OP_EQ,
    263            secret_to_key_derivekey(buf, sizeof(buf),
    264                                    (const uint8_t*)"", 0, "ABC", 3));
    265  tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
    266            secret_to_key_derivekey(buf, sizeof(buf),
    267                                    (const uint8_t*)"\x10", 1, "ABC", 3));
    268  tt_int_op(S2K_BAD_LEN, OP_EQ,
    269            secret_to_key_derivekey(buf, sizeof(buf),
    270                                    (const uint8_t*)"\x01\x02", 2, "ABC", 3));
    271 
    272  tt_int_op(S2K_BAD_LEN, OP_EQ,
    273            secret_to_key_check((const uint8_t*)"", 0, "ABC", 3));
    274  tt_int_op(S2K_BAD_ALGORITHM, OP_EQ,
    275            secret_to_key_check((const uint8_t*)"\x10", 1, "ABC", 3));
    276  tt_int_op(S2K_BAD_LEN, OP_EQ,
    277            secret_to_key_check((const uint8_t*)"\x01\x02", 2, "ABC", 3));
    278 
    279  /* too long gets "BAD_LEN" too */
    280  memset(buf, 0, sizeof(buf));
    281  buf[0] = 2;
    282  tt_int_op(S2K_BAD_LEN, OP_EQ,
    283            secret_to_key_derivekey(buf2, sizeof(buf2),
    284                                    buf, sizeof(buf), "ABC", 3));
    285 
    286  /* Truncated output */
    287 #ifdef HAVE_LIBSCRYPT
    288  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
    289                                                 "ABC", 3, 0));
    290  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 50, &sz,
    291                                                 "ABC", 3, S2K_FLAG_LOW_MEM));
    292 #endif /* defined(HAVE_LIBSCRYPT) */
    293  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 37, &sz,
    294                                              "ABC", 3, S2K_FLAG_USE_PBKDF2));
    295  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_new(buf, 29, &sz,
    296                                              "ABC", 3, S2K_FLAG_NO_SCRYPT));
    297 
    298 #ifdef HAVE_LIBSCRYPT
    299  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18, 0));
    300  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 18,
    301                                                 S2K_FLAG_LOW_MEM));
    302 #endif
    303  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 17,
    304                                                 S2K_FLAG_USE_PBKDF2));
    305  tt_int_op(S2K_TRUNCATED, OP_EQ, secret_to_key_make_specifier(buf, 9,
    306                                                 S2K_FLAG_NO_SCRYPT));
    307 
    308  /* Now try using type-specific bogus specifiers. */
    309 
    310  /* It's a bad pbkdf2 buffer if it has an iteration count that would overflow
    311   * int32_t. */
    312  memset(buf, 0, sizeof(buf));
    313  buf[0] = 1; /* pbkdf2 */
    314  buf[17] = 100; /* 1<<100 is much bigger than INT32_MAX */
    315  tt_int_op(S2K_BAD_PARAMS, OP_EQ,
    316            secret_to_key_derivekey(buf2, sizeof(buf2),
    317                                    buf, 18, "ABC", 3));
    318 
    319 #ifdef HAVE_LIBSCRYPT
    320  /* It's a bad scrypt buffer if N would overflow uint64 */
    321  memset(buf, 0, sizeof(buf));
    322  buf[0] = 2; /* scrypt */
    323  buf[17] = 100; /* 1<<100 is much bigger than UINT64_MAX */
    324  tt_int_op(S2K_BAD_PARAMS, OP_EQ,
    325            secret_to_key_derivekey(buf2, sizeof(buf2),
    326                                    buf, 19, "ABC", 3));
    327 #endif /* defined(HAVE_LIBSCRYPT) */
    328 
    329 done:
    330  ;
    331 }
    332 
    333 static void
    334 test_crypto_scrypt_vectors(void *arg)
    335 {
    336  char *mem_op_hex_tmp = NULL;
    337  uint8_t spec[64], out[64];
    338 
    339  (void)arg;
    340 #ifndef HAVE_LIBSCRYPT
    341  if (1)
    342    tt_skip();
    343 #endif
    344 
    345  /* Test vectors from
    346     https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00 section 11.
    347 
    348     Note that the names of 'r' and 'N' are switched in that section. Or
    349     possibly in libscrypt.
    350  */
    351 
    352  base16_decode((char*)spec, sizeof(spec),
    353                "0400", 4);
    354  memset(out, 0x00, sizeof(out));
    355  tt_int_op(64, OP_EQ,
    356            secret_to_key_compute_key(out, 64, spec, 2, "", 0, 2));
    357  test_memeq_hex(out,
    358                 "77d6576238657b203b19ca42c18a0497"
    359                 "f16b4844e3074ae8dfdffa3fede21442"
    360                 "fcd0069ded0948f8326a753a0fc81f17"
    361                 "e8d3e0fb2e0d3628cf35e20c38d18906");
    362 
    363  base16_decode((char*)spec, sizeof(spec),
    364                "4e61436c" "0A34", 12);
    365  memset(out, 0x00, sizeof(out));
    366  tt_int_op(64, OP_EQ,
    367            secret_to_key_compute_key(out, 64, spec, 6, "password", 8, 2));
    368  test_memeq_hex(out,
    369                 "fdbabe1c9d3472007856e7190d01e9fe"
    370                 "7c6ad7cbc8237830e77376634b373162"
    371                 "2eaf30d92e22a3886ff109279d9830da"
    372                 "c727afb94a83ee6d8360cbdfa2cc0640");
    373 
    374  base16_decode((char*)spec, sizeof(spec),
    375                "536f6469756d43686c6f72696465" "0e30", 32);
    376  memset(out, 0x00, sizeof(out));
    377  tt_int_op(64, OP_EQ,
    378            secret_to_key_compute_key(out, 64, spec, 16,
    379                                      "pleaseletmein", 13, 2));
    380  test_memeq_hex(out,
    381                 "7023bdcb3afd7348461c06cd81fd38eb"
    382                 "fda8fbba904f8e3ea9b543f6545da1f2"
    383                 "d5432955613f0fcf62d49705242a9af9"
    384                 "e61e85dc0d651e40dfcf017b45575887");
    385 
    386  base16_decode((char*)spec, sizeof(spec),
    387                "536f6469756d43686c6f72696465" "1430", 32);
    388  memset(out, 0x00, sizeof(out));
    389  tt_int_op(64, OP_EQ,
    390            secret_to_key_compute_key(out, 64, spec, 16,
    391                                      "pleaseletmein", 13, 2));
    392  test_memeq_hex(out,
    393                 "2101cb9b6a511aaeaddbbe09cf70f881"
    394                 "ec568d574a2ffd4dabe5ee9820adaa47"
    395                 "8e56fd8f4ba5d09ffa1c6d927c40f4c3"
    396                 "37304049e8a952fbcbf45c6fa77a41a4");
    397 
    398 done:
    399  tor_free(mem_op_hex_tmp);
    400 }
    401 
    402 static void
    403 test_crypto_pbkdf2_vectors(void *arg)
    404 {
    405  char *mem_op_hex_tmp = NULL;
    406  uint8_t spec[64], out[64];
    407  (void)arg;
    408 
    409  /* Test vectors from RFC6070, section 2 */
    410  base16_decode((char*)spec, sizeof(spec),
    411                "73616c74" "00" , 10);
    412  memset(out, 0x00, sizeof(out));
    413  tt_int_op(20, OP_EQ,
    414            secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
    415  test_memeq_hex(out, "0c60c80f961f0e71f3a9b524af6012062fe037a6");
    416 
    417  base16_decode((char*)spec, sizeof(spec),
    418                "73616c74" "01" , 10);
    419  memset(out, 0x00, sizeof(out));
    420  tt_int_op(20, OP_EQ,
    421            secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
    422  test_memeq_hex(out, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
    423 
    424  base16_decode((char*)spec, sizeof(spec),
    425                "73616c74" "0C" , 10);
    426  memset(out, 0x00, sizeof(out));
    427  tt_int_op(20, OP_EQ,
    428            secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
    429  test_memeq_hex(out, "4b007901b765489abead49d926f721d065a429c1");
    430 
    431  /* This is the very slow one here.  When enabled, it accounts for roughly
    432   * half the time spent in test-slow. */
    433  /*
    434  base16_decode((char*)spec, sizeof(spec),
    435                "73616c74" "18" , 10);
    436  memset(out, 0x00, sizeof(out));
    437  tt_int_op(20, OP_EQ,
    438            secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
    439  test_memeq_hex(out, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
    440  */
    441 
    442  base16_decode((char*)spec, sizeof(spec),
    443                "73616c7453414c5473616c7453414c5473616c745"
    444                "3414c5473616c7453414c5473616c74" "0C" , 74);
    445  memset(out, 0x00, sizeof(out));
    446  tt_int_op(25, OP_EQ,
    447            secret_to_key_compute_key(out, 25, spec, 37,
    448                                      "passwordPASSWORDpassword", 24, 1));
    449  test_memeq_hex(out, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
    450 
    451  base16_decode((char*)spec, sizeof(spec),
    452                "7361006c74" "0c" , 12);
    453  memset(out, 0x00, sizeof(out));
    454  tt_int_op(16, OP_EQ,
    455            secret_to_key_compute_key(out, 16, spec, 6, "pass\0word", 9, 1));
    456  test_memeq_hex(out, "56fa6aa75548099dcc37d7f03425e0c3");
    457 
    458 done:
    459  tor_free(mem_op_hex_tmp);
    460 }
    461 
    462 static void
    463 test_crypto_pwbox(void *arg)
    464 {
    465  uint8_t *boxed=NULL, *decoded=NULL;
    466  size_t len, dlen;
    467  unsigned i;
    468  const char msg[] = "This bunny reminds you that you still have a "
    469    "salamander in your sylladex. She is holding the bunny Dave got you. "
    470    "It’s sort of uncanny how similar they are, aside from the knitted "
    471    "enhancements. Seriously, what are the odds?? So weird.";
    472  const char pw[] = "I'm a night owl and a wise bird too";
    473 
    474  const unsigned flags[] = { 0,
    475                             S2K_FLAG_NO_SCRYPT,
    476                             S2K_FLAG_LOW_MEM,
    477                             S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM,
    478                             S2K_FLAG_USE_PBKDF2 };
    479  (void)arg;
    480 
    481  for (i = 0; i < ARRAY_LENGTH(flags); ++i) {
    482    tt_int_op(0, OP_EQ, crypto_pwbox(&boxed, &len,
    483                                  (const uint8_t*)msg, strlen(msg),
    484                                  pw, strlen(pw), flags[i]));
    485    tt_assert(boxed);
    486    tt_assert(len > 128+32);
    487 
    488    tt_int_op(0, OP_EQ, crypto_unpwbox(&decoded, &dlen, boxed, len,
    489                                    pw, strlen(pw)));
    490 
    491    tt_assert(decoded);
    492    tt_uint_op(dlen, OP_EQ, strlen(msg));
    493    tt_mem_op(decoded, OP_EQ, msg, dlen);
    494 
    495    tor_free(decoded);
    496 
    497    tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
    498                                                     boxed, len,
    499                                                     pw, strlen(pw)-1));
    500    boxed[len-1] ^= 1;
    501    tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
    502                                                     boxed, len,
    503                                                     pw, strlen(pw)));
    504    boxed[0] = 255;
    505    tt_int_op(UNPWBOX_CORRUPTED, OP_EQ, crypto_unpwbox(&decoded, &dlen,
    506                                                    boxed, len,
    507                                                    pw, strlen(pw)));
    508 
    509    tor_free(boxed);
    510  }
    511 
    512 done:
    513  tor_free(boxed);
    514  tor_free(decoded);
    515 }
    516 
    517 static void
    518 test_crypto_ed25519_fuzz_donna(void *arg)
    519 {
    520  const unsigned iters = 1024;
    521  uint8_t msg[1024];
    522  unsigned i;
    523  (void)arg;
    524 
    525  tt_uint_op(iters, OP_EQ, sizeof(msg));
    526  crypto_rand((char*) msg, sizeof(msg));
    527 
    528  /* Fuzz Ed25519-donna vs ref10, alternating the implementation used to
    529   * generate keys/sign per iteration.
    530   */
    531  for (i = 0; i < iters; ++i) {
    532    const int use_donna = i & 1;
    533    uint8_t blinding[32];
    534    curve25519_keypair_t ckp;
    535    ed25519_keypair_t kp, kp_blind, kp_curve25519;
    536    ed25519_public_key_t pk, pk_blind, pk_curve25519;
    537    ed25519_signature_t sig, sig_blind;
    538    int bit = 0;
    539 
    540    crypto_rand((char*) blinding, sizeof(blinding));
    541 
    542    /* Impl. A:
    543     *  1. Generate a keypair.
    544     *  2. Blinded the keypair.
    545     *  3. Sign a message (unblinded).
    546     *  4. Sign a message (blinded).
    547     *  5. Generate a curve25519 keypair, and convert it to Ed25519.
    548     */
    549    ed25519_set_impl_params(use_donna);
    550    tt_int_op(0, OP_EQ, ed25519_keypair_generate(&kp, i&1));
    551    tt_int_op(0, OP_EQ, ed25519_keypair_blind(&kp_blind, &kp, blinding));
    552    tt_int_op(0, OP_EQ, ed25519_sign(&sig, msg, i, &kp));
    553    tt_int_op(0, OP_EQ, ed25519_sign(&sig_blind, msg, i, &kp_blind));
    554 
    555    tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ckp, i&1));
    556    tt_int_op(0, OP_EQ, ed25519_keypair_from_curve25519_keypair(
    557            &kp_curve25519, &bit, &ckp));
    558 
    559    /* Impl. B:
    560     *  1. Validate the public key by rederiving it.
    561     *  2. Validate the blinded public key by rederiving it.
    562     *  3. Validate the unblinded signature (and test a invalid signature).
    563     *  4. Validate the blinded signature.
    564     *  5. Validate the public key (from Curve25519) by rederiving it.
    565     */
    566    ed25519_set_impl_params(!use_donna);
    567    tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pk, &kp.seckey));
    568    tt_mem_op(pk.pubkey, OP_EQ, kp.pubkey.pubkey, 32);
    569 
    570    tt_int_op(0, OP_EQ, ed25519_public_blind(&pk_blind, &kp.pubkey, blinding));
    571    tt_mem_op(pk_blind.pubkey, OP_EQ, kp_blind.pubkey.pubkey, 32);
    572 
    573    tt_int_op(0, OP_EQ, ed25519_checksig(&sig, msg, i, &pk));
    574    sig.sig[0] ^= 15;
    575    tt_int_op(-1, OP_EQ, ed25519_checksig(&sig, msg, sizeof(msg), &pk));
    576 
    577    tt_int_op(0, OP_EQ, ed25519_checksig(&sig_blind, msg, i, &pk_blind));
    578 
    579    tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key(
    580            &pk_curve25519, &ckp.pubkey, bit));
    581    tt_mem_op(pk_curve25519.pubkey, OP_EQ, kp_curve25519.pubkey.pubkey, 32);
    582  }
    583 
    584 done:
    585  ;
    586 }
    587 
    588 static void
    589 test_crypto_equix(void *arg)
    590 {
    591  (void)arg;
    592 
    593  static const struct {
    594    const char *challenge_literal;
    595    size_t num_solutions;
    596    equix_solution solutions[EQUIX_MAX_SOLS];
    597  } vectors[] = {
    598    { "zzz", 1, {
    599      {{ 0xae21, 0xd392, 0x3215, 0xdd9c, 0x2f08, 0x93df, 0x232c, 0xe5dc }},
    600    }},
    601    { "rrr", 1, {
    602      {{ 0x0873, 0x57a8, 0x73e0, 0x912e, 0x1ca8, 0xad96, 0x9abd, 0xd7de }},
    603    }},
    604    { "qqq", 0, {{{ 0 }}} },
    605    { "0123456789", 0, {{{ 0 }}} },
    606    { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0, {{{ 0 }}} },
    607    { "", 3, {
    608      {{ 0x0098, 0x3a4d, 0xc489, 0xcfba, 0x7ef3, 0xa498, 0xa00f, 0xec20 }},
    609      {{ 0x78d8, 0x8611, 0xa4df, 0xec19, 0x0927, 0xa729, 0x842f, 0xf771 }},
    610      {{ 0x54b5, 0xcc11, 0x1593, 0xe624, 0x9357, 0xb339, 0xb138, 0xed99 }},
    611    }},
    612    { "a", 3, {
    613      {{ 0x4b38, 0x8c81, 0x9255, 0xad99, 0x5ce7, 0xeb3e, 0xc635, 0xee38 }},
    614      {{ 0x3f9e, 0x659b, 0x9ae6, 0xb891, 0x63ae, 0x777c, 0x06ca, 0xc593 }},
    615      {{ 0x2227, 0xa173, 0x365a, 0xb47d, 0x1bb2, 0xa077, 0x0d5e, 0xf25f }},
    616    }},
    617    { "abc", 2, {
    618      {{ 0x371f, 0x8865, 0x8189, 0xfbc3, 0x26df, 0xe4c0, 0xab39, 0xfe5a }},
    619      {{ 0x2101, 0xb88f, 0xc525, 0xccb3, 0x5785, 0xa41e, 0x4fba, 0xed18 }},
    620    }},
    621    { "abce", 4, {
    622      {{ 0x4fca, 0x72eb, 0x101f, 0xafab, 0x1add, 0x2d71, 0x75a3, 0xc978 }},
    623      {{ 0x17f1, 0x7aa6, 0x23e3, 0xab00, 0x7e2f, 0x917e, 0x16da, 0xda9e }},
    624      {{ 0x70ee, 0x7757, 0x8a54, 0xbd2b, 0x90e4, 0xe31e, 0x2085, 0xe47e }},
    625      {{ 0x62c5, 0x86d1, 0x5752, 0xe1f0, 0x12da, 0x8f33, 0x7336, 0xf161 }},
    626    }},
    627    { "01234567890123456789", 5, {
    628      {{ 0x4803, 0x6775, 0xc5c9, 0xd1b0, 0x1bc3, 0xe4f6, 0x4027, 0xf5ad }},
    629      {{ 0x5a8a, 0x9542, 0xef99, 0xf0b9, 0x4905, 0x4e29, 0x2da5, 0xfbd5 }},
    630      {{ 0x4c79, 0xc935, 0x2bcb, 0xcd0f, 0x0362, 0x9fa9, 0xa62e, 0xf83a }},
    631      {{ 0x5878, 0x6edf, 0x1e00, 0xf5e3, 0x43de, 0x9212, 0xd01e, 0xfd11 }},
    632      {{ 0x0b69, 0x2d17, 0x01be, 0x6cb4, 0x0fba, 0x4a9e, 0x8d75, 0xa50f }},
    633    }},
    634  };
    635 
    636  static const struct {
    637    equix_ctx_flags flags;
    638    equix_result expected;
    639    equix_solution_flags sol_flags;
    640  } variations[] = {
    641    {0, EQUIX_OK, 0},
    642    {0, EQUIX_FAIL_ORDER, 0},
    643    {0, EQUIX_FAIL_PARTIAL_SUM, 0},
    644 #if defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__)
    645    { EQUIX_CTX_MUST_COMPILE, EQUIX_OK,
    646      EQUIX_SOLVER_DID_USE_COMPILER
    647    },
    648    { EQUIX_CTX_MUST_COMPILE, EQUIX_FAIL_ORDER,
    649      EQUIX_SOLVER_DID_USE_COMPILER
    650    },
    651    { EQUIX_CTX_MUST_COMPILE, EQUIX_FAIL_PARTIAL_SUM,
    652      EQUIX_SOLVER_DID_USE_COMPILER
    653    },
    654 #endif
    655  };
    656 
    657  const unsigned num_vectors = sizeof vectors / sizeof vectors[0];
    658  const unsigned num_variations = sizeof variations / sizeof variations[0];
    659 
    660  for (unsigned vec_i = 0; vec_i < num_vectors; vec_i++) {
    661    const char *challenge_literal = vectors[vec_i].challenge_literal;
    662    const size_t challenge_len = strlen(challenge_literal);
    663 
    664    const size_t num_sols = vectors[vec_i].num_solutions;
    665    const equix_solution *sols_expected = vectors[vec_i].solutions;
    666 
    667    for (unsigned vari_i = 0; vari_i < num_variations; vari_i++) {
    668      const equix_ctx_flags flags = variations[vari_i].flags;
    669      const equix_solution_flags sol_flags = variations[vari_i].sol_flags;
    670      const equix_result expected = variations[vari_i].expected;
    671 
    672      equix_solutions_buffer output;
    673      equix_ctx *solve_ctx = NULL, *verify_ctx = NULL;
    674 
    675      solve_ctx = equix_alloc(EQUIX_CTX_SOLVE | flags);
    676      tt_ptr_op(solve_ctx, OP_NE, NULL);
    677 
    678      /* Solve phase: Make sure the test vector matches */
    679      memset(&output, 0xa5, sizeof output);
    680      equix_result result;
    681      result = equix_solve(solve_ctx, challenge_literal,
    682                           challenge_len, &output);
    683      equix_free(solve_ctx);
    684      tt_int_op(result, OP_EQ, EQUIX_OK);
    685      tt_int_op(output.count, OP_EQ, num_sols);
    686      tt_int_op(output.flags, OP_EQ, sol_flags);
    687      tt_mem_op(output.sols, OP_EQ, sols_expected,
    688                num_sols * sizeof(equix_solution));
    689 
    690      verify_ctx = equix_alloc(EQUIX_CTX_VERIFY | flags);
    691      tt_ptr_op(verify_ctx, OP_NE, NULL);
    692 
    693      /* Use each solution for positive and negative tests of verify */
    694      for (size_t sol_i = 0; sol_i < num_sols; sol_i++) {
    695        equix_idx tmp_idx;
    696        equix_solution *sol = &output.sols[sol_i];
    697 
    698        if (expected == EQUIX_FAIL_ORDER) {
    699          /* Swap two otherwise valid indices, to trigger an order error */
    700          tmp_idx = sol->idx[0];
    701          sol->idx[0] = sol->idx[1];
    702          sol->idx[1] = tmp_idx;
    703        } else if (expected == EQUIX_FAIL_PARTIAL_SUM) {
    704          /* Most changes to the solution will cause a partial sum error */
    705          sol->idx[0]++;
    706        }
    707 
    708        result = equix_verify(verify_ctx, challenge_literal,
    709                              challenge_len, sol);
    710        tt_int_op(expected, OP_EQ, result);
    711      }
    712 
    713      equix_free(verify_ctx);
    714    }
    715  }
    716 
    717 done:
    718  ;
    719 }
    720 
    721 #ifndef COCCI
    722 #define CRYPTO_LEGACY(name)                                            \
    723  { #name, test_crypto_ ## name , 0, NULL, NULL }
    724 
    725 #define ED25519_TEST_ONE(name, fl, which)                               \
    726  { #name "/ed25519_" which, test_crypto_ed25519_ ## name, (fl),        \
    727    &ed25519_test_setup, (void*)which }
    728 
    729 #define ED25519_TEST(name, fl)                  \
    730  ED25519_TEST_ONE(name, (fl), "donna"),        \
    731  ED25519_TEST_ONE(name, (fl), "ref10")
    732 #endif /* !defined(COCCI) */
    733 
    734 struct testcase_t slow_crypto_tests[] = {
    735  CRYPTO_LEGACY(s2k_rfc2440),
    736 #ifdef HAVE_LIBSCRYPT
    737  { "s2k_scrypt", test_crypto_s2k_general, 0, &passthrough_setup,
    738    (void*)"scrypt" },
    739  { "s2k_scrypt_low", test_crypto_s2k_general, 0, &passthrough_setup,
    740    (void*)"scrypt-low" },
    741 #ifdef HAVE_EVP_PBE_SCRYPT
    742  { "libscrypt_eq_openssl", test_libscrypt_eq_openssl, 0, NULL, NULL },
    743 #endif
    744 #endif /* defined(HAVE_LIBSCRYPT) */
    745  { "s2k_pbkdf2", test_crypto_s2k_general, 0, &passthrough_setup,
    746    (void*)"pbkdf2" },
    747  { "s2k_rfc2440_general", test_crypto_s2k_general, 0, &passthrough_setup,
    748    (void*)"rfc2440" },
    749  { "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &passthrough_setup,
    750    (void*)"rfc2440-legacy" },
    751  { "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL },
    752  { "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL },
    753  { "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL },
    754  { "pwbox", test_crypto_pwbox, 0, NULL, NULL },
    755  ED25519_TEST(fuzz_donna, TT_FORK),
    756  { "equix", test_crypto_equix, 0, NULL, NULL },
    757  END_OF_TESTCASES
    758 };