tor

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

test_crypto_cgo.c (19753B)


      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 #define RELAY_CRYPTO_CGO_PRIVATE
      7 #define USE_AES_RAW
      8 
      9 #include "orconfig.h"
     10 #include "core/or/or.h"
     11 #include "test/test.h"
     12 #include "lib/cc/compat_compiler.h"
     13 #include "lib/crypt_ops/aes.h"
     14 #include "ext/polyval/polyval.h"
     15 #include "core/crypto/relay_crypto_cgo.h"
     16 #include "lib/crypt_ops/crypto_rand.h"
     17 #include "lib/crypt_ops/crypto_util.h"
     18 #include "core/or/cell_st.h"
     19 
     20 #include "test/cgo_vectors.inc"
     21 
     22 static const int AESBITS[] = { 128, 192, 256 };
     23 
     24 static void
     25 test_crypto_cgo_et_roundtrip(void *arg)
     26 {
     27  (void)arg;
     28  uint8_t key[32 + 16]; // max
     29  uint8_t tweak_h[16];
     30  uint8_t tweak_x_r[493];
     31  uint8_t block[16], block_orig[16];
     32  cgo_et_t et1, et2;
     33  memset(&et1, 0, sizeof(et1));
     34  memset(&et2, 0, sizeof(et2));
     35 
     36  et_tweak_t tweak = {
     37    .uiv = {
     38      .h = tweak_h,
     39      .cmd = 7,
     40    },
     41    .x_r = tweak_x_r,
     42  };
     43 
     44  for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) {
     45    const int aesbits = AESBITS[bi];
     46 
     47    for (int i = 0; i < 16; ++i) {
     48      crypto_rand((char*)key, sizeof(key));
     49      crypto_rand((char*)tweak_h, sizeof(tweak_h));
     50      crypto_rand((char*)tweak_x_r, sizeof(tweak_x_r));
     51      crypto_rand((char*)block_orig, sizeof(block_orig));
     52      memcpy(block, block_orig, 16);
     53      cgo_et_init(&et1, aesbits, true, key);
     54      cgo_et_init(&et2, aesbits, false, key);
     55 
     56      // encrypt-then-decrypt should round-trip.
     57      cgo_et_encrypt(&et1, tweak, block);
     58      tt_mem_op(block, OP_NE, block_orig, 16);
     59      cgo_et_decrypt(&et2, tweak, block);
     60      tt_mem_op(block, OP_EQ, block_orig, 16);
     61 
     62      // decrypt-then-encrypt should round-trip.
     63      cgo_et_decrypt(&et2, tweak, block);
     64      tt_mem_op(block, OP_NE, block_orig, 16);
     65      cgo_et_encrypt(&et1, tweak, block);
     66      tt_mem_op(block, OP_EQ, block_orig, 16);
     67 
     68      cgo_et_clear(&et1);
     69      cgo_et_clear(&et2);
     70    }
     71  }
     72 done:
     73  cgo_et_clear(&et1);
     74  cgo_et_clear(&et2);
     75 }
     76 
     77 static void
     78 test_crypto_cgo_uiv_roundtrip(void *arg)
     79 {
     80  (void)arg;
     81  uint8_t key[64 + 32]; // max
     82  uint8_t tweak_h[16];
     83  uint8_t cell[509], cell_orig[509];
     84  cgo_uiv_t uiv1, uiv2;
     85  memset(&uiv1, 0, sizeof(uiv1));
     86  memset(&uiv2, 0, sizeof(uiv2));
     87 
     88  uiv_tweak_t tweak = {
     89    .h = tweak_h,
     90    .cmd = 4,
     91  };
     92 
     93  for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) {
     94    const int aesbits = AESBITS[bi];
     95 
     96    for (int i = 0; i < 16; ++i) {
     97      crypto_rand((char*)key, sizeof(key));
     98      crypto_rand((char*)tweak_h, sizeof(tweak_h));
     99      crypto_rand((char*)cell_orig, sizeof(cell_orig));
    100      memcpy(cell, cell_orig, sizeof(cell_orig));
    101 
    102      cgo_uiv_init(&uiv1, aesbits, true, key);
    103      cgo_uiv_init(&uiv2, aesbits, false, key);
    104 
    105      // encrypt-then-decrypt should round-trip.
    106      cgo_uiv_encrypt(&uiv1, tweak, cell);
    107      tt_mem_op(cell, OP_NE, cell_orig, sizeof(cell));
    108      cgo_uiv_decrypt(&uiv2, tweak, cell);
    109      tt_mem_op(cell, OP_EQ, cell_orig, sizeof(cell));
    110 
    111      // decrypt-then-encrypt should round-trip.
    112      cgo_uiv_decrypt(&uiv2, tweak, cell);
    113      tt_mem_op(cell, OP_NE, cell_orig, sizeof(cell));
    114      cgo_uiv_encrypt(&uiv1, tweak, cell);
    115      tt_mem_op(cell, OP_EQ, cell_orig, sizeof(cell));
    116 
    117      cgo_uiv_clear(&uiv1);
    118      cgo_uiv_clear(&uiv2);
    119    }
    120  }
    121 done:
    122  cgo_uiv_clear(&uiv1);
    123  cgo_uiv_clear(&uiv2);
    124 }
    125 
    126 #define UNHEX(out,inp) STMT_BEGIN {                                     \
    127    size_t inplen = strlen(inp);                                        \
    128    tt_int_op(sizeof(out), OP_EQ, inplen / 2);                          \
    129    int r = base16_decode((char*)(out), sizeof(out), inp, inplen);      \
    130    tt_int_op(r, OP_EQ, sizeof(out));                                   \
    131  } STMT_END
    132 
    133 #define UNHEX2(out,inp1,inp2) STMT_BEGIN {                              \
    134    tor_free(unhex_tmp);                                                \
    135    tor_asprintf(&unhex_tmp, "%s%s", inp1, inp2);                       \
    136    UNHEX(out, unhex_tmp);                                              \
    137  } STMT_END
    138 
    139 static void
    140 test_crypto_cgo_et_testvec(void *arg)
    141 {
    142  (void)arg;
    143  cgo_et_t et;
    144  memset(&et, 0, sizeof(et));
    145 
    146  for (int i = 0; i < (int)ARRAY_LENGTH(ET_TESTVECS); ++i) {
    147    const struct et_testvec *tv = &ET_TESTVECS[i];
    148    uint8_t keys[32];
    149    uint8_t tweaks[16 + 1 + 493];
    150    uint8_t block[16], expect[16];
    151    UNHEX(keys, tv->keys);
    152    UNHEX(tweaks, tv->tweaks);
    153    UNHEX(block, tv->block);
    154    UNHEX(expect, tv->expect);
    155 
    156    et_tweak_t tweak = {
    157      .uiv = {
    158        .h = tweaks,
    159        .cmd = tweaks[16],
    160      },
    161      .x_r = tweaks + 17,
    162    };
    163 
    164    cgo_et_init(&et, 128, tv->encrypt, keys);
    165    if (tv->encrypt) {
    166      cgo_et_encrypt(&et, tweak, block);
    167    } else {
    168      cgo_et_decrypt(&et, tweak, block);
    169    }
    170    cgo_et_clear(&et);
    171 
    172    tt_mem_op(block, OP_EQ, expect, 16);
    173  }
    174 
    175 done:
    176  cgo_et_clear(&et);
    177 }
    178 
    179 static void
    180 test_crypto_cgo_prf_testvec(void *arg)
    181 {
    182  (void)arg;
    183  cgo_prf_t prf;
    184  memset(&prf, 0, sizeof(prf));
    185 
    186  for (int i = 0; i < (int)ARRAY_LENGTH(PRF_TESTVECS); ++i) {
    187    const struct prf_testvec *tv = &PRF_TESTVECS[i];
    188    uint8_t keys[32];
    189    uint8_t input[16];
    190    uint8_t expect_t0[493];
    191    uint8_t expect_t1[80];
    192    uint8_t output[493]; // max
    193    UNHEX(keys, tv->keys);
    194    UNHEX(input, tv->input);
    195 
    196    cgo_prf_init(&prf, 128, keys);
    197    if (tv->t == 0) {
    198      UNHEX(expect_t0, tv->expect);
    199      memset(output, 0, sizeof(output));
    200      cgo_prf_xor_t0(&prf, input, output);
    201      tt_mem_op(output, OP_EQ, expect_t0, PRF_T0_DATA_LEN);
    202    } else {
    203      tt_int_op(tv->t, OP_EQ, 1);
    204      UNHEX(expect_t1, tv->expect);
    205      cgo_prf_gen_t1(&prf, input, output, sizeof(expect_t1));
    206      tt_mem_op(output, OP_EQ, expect_t1, sizeof(expect_t1));
    207    }
    208    cgo_prf_clear(&prf);
    209  }
    210 done:
    211  cgo_prf_clear(&prf);
    212 }
    213 
    214 static void
    215 test_crypto_cgo_uiv_testvec(void *arg)
    216 {
    217  (void)arg;
    218  cgo_uiv_t uiv;
    219  memset(&uiv, 0, sizeof(uiv));
    220 
    221  for (int i = 0; i < (int)ARRAY_LENGTH(UIV_TESTVECS); ++i) {
    222    const struct uiv_testvec *tv = &UIV_TESTVECS[i];
    223    uint8_t keys[64];
    224    uint8_t tweaks[17];
    225    uint8_t x_l[16], x_r[493];
    226    uint8_t y_l[16], y_r[493];
    227    uint8_t cell[509];
    228    UNHEX(keys, tv->keys);
    229    UNHEX(tweaks, tv->tweaks);
    230    UNHEX(x_l, tv->x_l);
    231    UNHEX(x_r, tv->x_r);
    232    UNHEX(y_l, tv->y.y_l);
    233    UNHEX(y_r, tv->y.y_r);
    234 
    235    uiv_tweak_t tweak = {
    236      .h = tweaks,
    237      .cmd = tweaks[16]
    238    };
    239    memcpy(cell, x_l, 16);
    240    memcpy(cell+16, x_r, 493);
    241 
    242    cgo_uiv_init(&uiv, 128, tv->encrypt, keys);
    243    if (tv->encrypt) {
    244      cgo_uiv_encrypt(&uiv, tweak, cell);
    245    } else {
    246      cgo_uiv_decrypt(&uiv, tweak, cell);
    247    }
    248    cgo_uiv_clear(&uiv);
    249 
    250    tt_mem_op(cell, OP_EQ, y_l, 16);
    251    tt_mem_op(cell+16, OP_EQ, y_r, 493);
    252  }
    253 
    254 done:
    255  cgo_uiv_clear(&uiv);
    256 }
    257 
    258 #include "core/crypto/relay_crypto_st.h"
    259 
    260 static void
    261 test_crypto_cgo_uiv_update_testvec(void *arg)
    262 {
    263  (void)arg;
    264  cgo_uiv_t uiv;
    265  cgo_uiv_t uiv2;
    266  memset(&uiv, 0, sizeof(uiv));
    267  memset(&uiv2, 0, sizeof(uiv2));
    268 
    269  uint8_t tw[16];
    270  memset(tw, 42, sizeof(tw));
    271  uiv_tweak_t tweak = {
    272      .h = tw,
    273      .cmd = 42
    274  };
    275 
    276  for (int i = 0; i < (int)ARRAY_LENGTH(UIV_UPDATE_TESTVECS); ++i) {
    277    const struct uiv_update_testvec *tv = &UIV_UPDATE_TESTVECS[i];
    278    uint8_t keys[64];
    279    uint8_t nonce[16];
    280    uint8_t new_keys[64];
    281    uint8_t new_nonce[16];
    282    UNHEX(keys, tv->keys);
    283    UNHEX(nonce, tv->nonce);
    284    UNHEX(new_keys, tv->output.new_keys);
    285    UNHEX(new_nonce, tv->output.new_nonce);
    286 
    287    cgo_uiv_init(&uiv, 128, true, keys);
    288    cgo_uiv_update(&uiv, 128, true, nonce);
    289    // Make sure that the recorded keys are what we expect.
    290    tt_mem_op(uiv.uiv_keys_, OP_EQ, new_keys, 64);
    291    tt_mem_op(nonce, OP_EQ, new_nonce, 16);
    292 
    293    // Construct a new UIV from these keys and make sure it acts like this one.
    294    uint8_t cell[509], cell2[509];
    295    crypto_rand((char*)cell, sizeof(cell));
    296    memcpy(cell2, cell, 509);
    297    cgo_uiv_init(&uiv2, 128, true, uiv.uiv_keys_);
    298    cgo_uiv_encrypt(&uiv, tweak, cell);
    299    cgo_uiv_encrypt(&uiv2, tweak, cell2);
    300    tt_mem_op(cell, OP_EQ, cell2, 509);
    301 
    302    cgo_uiv_clear(&uiv);
    303    cgo_uiv_clear(&uiv2);
    304  }
    305 done:
    306  cgo_uiv_clear(&uiv);
    307  cgo_uiv_clear(&uiv2);
    308 }
    309 
    310 static void
    311 test_crypto_cgo_fwd(void *arg)
    312 {
    313  (void)arg;
    314 
    315  #define N_HOPS 3
    316  uint8_t key_material[N_HOPS][112]; // max.
    317  cgo_crypt_t *client[N_HOPS];
    318  cgo_crypt_t *relays[N_HOPS];
    319 
    320  memset(client, 0, sizeof(client));
    321  memset(relays, 0, sizeof(relays));
    322 
    323  for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) {
    324    const int aesbits = AESBITS[bi];
    325 
    326    size_t klen = cgo_key_material_len(aesbits);
    327    tt_uint_op(klen, OP_LE, sizeof(key_material[0]));
    328    crypto_rand((char*)&key_material, sizeof(key_material));
    329    for (int i = 0; i < N_HOPS; ++i) {
    330      client[i] = cgo_crypt_new(CGO_MODE_CLIENT_FORWARD,
    331                                aesbits, key_material[i], klen);
    332      relays[i] = cgo_crypt_new(CGO_MODE_RELAY_FORWARD,
    333                                aesbits, key_material[i], klen);
    334    }
    335    for (int trial = 0; trial < 64; ++trial) {
    336      int target_hop = crypto_rand_int(3);
    337      cell_t cell, cell_orig;
    338      uint8_t tag_client[SENDME_TAG_LEN_CGO];
    339      const uint8_t *tagp = NULL;
    340 
    341      memset(&cell, 0, sizeof(cell));
    342      if (crypto_rand_int(2) == 0) {
    343        cell.command = CELL_RELAY;
    344      } else {
    345        cell.command = CELL_RELAY_EARLY;
    346      }
    347      crypto_rand((char*) cell.payload+SENDME_TAG_LEN_CGO,
    348                  sizeof(cell.payload)-SENDME_TAG_LEN_CGO);
    349      memcpy(&cell_orig, &cell, sizeof(cell));
    350 
    351      // First the client encrypts the cell...
    352      cgo_crypt_client_originate(client[target_hop], &cell, &tagp);
    353      tt_assert(tagp);
    354      memcpy(tag_client, tagp, SENDME_TAG_LEN_CGO);
    355      for (int i = target_hop - 1; i >= 0; --i) {
    356        cgo_crypt_client_forward(client[i], &cell);
    357      }
    358 
    359      // Now the relays handle the cell...
    360      bool cell_recognized = false;
    361      for (int i = 0; i < N_HOPS; ++i) {
    362        tagp = NULL;
    363        cgo_crypt_relay_forward(relays[i], &cell, &tagp);
    364        if (tagp) {
    365          tt_int_op(i, OP_EQ, target_hop);
    366          tt_mem_op(tagp, OP_EQ, tag_client, SENDME_TAG_LEN_CGO);
    367          cell_recognized = true;
    368          break;
    369        }
    370      }
    371      tt_assert(cell_recognized);
    372      tt_int_op(cell.command, OP_EQ, cell_orig.command);
    373      tt_mem_op(cell.payload + SENDME_TAG_LEN_CGO, OP_EQ,
    374                cell_orig.payload + SENDME_TAG_LEN_CGO,
    375                sizeof(cell.payload) - SENDME_TAG_LEN_CGO);
    376    }
    377    for (int i = 0; i < N_HOPS; ++i) {
    378      cgo_crypt_free(client[i]);
    379      cgo_crypt_free(relays[i]);
    380    }
    381  }
    382 
    383 done:
    384  for (int i = 0; i < N_HOPS; ++i) {
    385    cgo_crypt_free(client[i]);
    386    cgo_crypt_free(relays[i]);
    387  }
    388 #undef N_HOPS
    389 }
    390 
    391 static void
    392 test_crypto_cgo_rev(void *arg)
    393 {
    394  (void)arg;
    395 
    396  #define N_HOPS 3
    397  uint8_t key_material[N_HOPS][112]; // max.
    398  cgo_crypt_t *client[N_HOPS];
    399  cgo_crypt_t *relays[N_HOPS];
    400 
    401  memset(client, 0, sizeof(client));
    402  memset(relays, 0, sizeof(relays));
    403 
    404  for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) {
    405    const int aesbits = AESBITS[bi];
    406 
    407    size_t klen = cgo_key_material_len(aesbits);
    408    tt_uint_op(klen, OP_LE, sizeof(key_material[0]));
    409    crypto_rand((char*)&key_material, sizeof(key_material));
    410    for (int i = 0; i < N_HOPS; ++i) {
    411      client[i] = cgo_crypt_new(CGO_MODE_CLIENT_BACKWARD,
    412                                 aesbits, key_material[i], klen);
    413      relays[i] = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD,
    414                                aesbits, key_material[i], klen);
    415    }
    416    for (int trial = 0; trial < 64; ++trial) {
    417      int origin_hop = crypto_rand_int(3);
    418      cell_t cell, cell_orig;
    419      uint8_t tag_relay[SENDME_TAG_LEN_CGO];
    420      const uint8_t *tagp = NULL;
    421 
    422      memset(&cell, 0, sizeof(cell));
    423      cell.command = CELL_RELAY;
    424      crypto_rand((char*) cell.payload+SENDME_TAG_LEN_CGO,
    425                  sizeof(cell.payload)-SENDME_TAG_LEN_CGO);
    426      memcpy(&cell_orig, &cell, sizeof(cell));
    427 
    428      // First the specified relay encrypts the cell...
    429      cgo_crypt_relay_originate(relays[origin_hop], &cell, &tagp);
    430      tt_assert(tagp);
    431      memcpy(tag_relay, tagp, SENDME_TAG_LEN_CGO);
    432      for (int i = origin_hop - 1; i >= 0; --i) {
    433        cgo_crypt_relay_backward(relays[i], &cell);
    434      }
    435 
    436      // Now the client handles the cell.
    437      bool cell_recognized = false;
    438      for (int i = 0; i < N_HOPS; ++i) {
    439        tagp = NULL;
    440        cgo_crypt_client_backward(client[i], &cell, &tagp);
    441        if (tagp) {
    442          tt_int_op(i, OP_EQ, origin_hop);
    443          tt_mem_op(tagp, OP_EQ, tag_relay, SENDME_TAG_LEN_CGO);
    444          cell_recognized = true;
    445          break;
    446        }
    447      }
    448      tt_assert(cell_recognized);
    449      tt_int_op(cell.command, OP_EQ, cell_orig.command);
    450      tt_mem_op(cell.payload + SENDME_TAG_LEN_CGO, OP_EQ,
    451                cell_orig.payload + SENDME_TAG_LEN_CGO,
    452                sizeof(cell.payload) - SENDME_TAG_LEN_CGO);
    453    }
    454    for (int i = 0; i < N_HOPS; ++i) {
    455      cgo_crypt_free(client[i]);
    456      cgo_crypt_free(relays[i]);
    457    }
    458  }
    459 
    460 done:
    461  for (int i = 0; i < N_HOPS; ++i) {
    462    cgo_crypt_free(client[i]);
    463    cgo_crypt_free(relays[i]);
    464  }
    465 #undef N_HOPS
    466 }
    467 
    468 static void
    469 test_crypto_cgo_relay_testvec(void *arg)
    470 {
    471  (void)arg;
    472  char *unhex_tmp = NULL;
    473  cgo_crypt_t *cgo = NULL;
    474  for (int i = 0; i < (int)ARRAY_LENGTH(CGO_RELAY_TESTVECS); ++i) {
    475    const struct cgo_relay_testvec *tv = &CGO_RELAY_TESTVECS[i];
    476    const int aesbits = 128;
    477    uint8_t keys[80], expect_keys[80], expect_tprime[SENDME_TAG_LEN_CGO],
    478      cmd[1];
    479    cell_t cell;
    480    cell_t expect_cell;
    481    tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits));
    482    UNHEX2(keys, tv->state_in.keys, tv->state_in.nonce);
    483    cgo_mode_t mode =
    484      tv->inbound ? CGO_MODE_RELAY_BACKWARD : CGO_MODE_RELAY_FORWARD;
    485    cgo = cgo_crypt_new(mode, aesbits, keys, sizeof(keys));
    486    tt_assert(cgo);
    487    UNHEX(cgo->tprime, tv->state_in.tprime);
    488    memset(&cell, 0, sizeof(cell));
    489    UNHEX(cmd, tv->cmd);
    490    cell.command = cmd[0];
    491    UNHEX2(cell.payload, tv->tag, tv->msg);
    492 
    493    memset(&expect_cell, 0, sizeof(expect_cell));
    494    expect_cell.command = cell.command;
    495    UNHEX2(expect_cell.payload,
    496           tv->output.result.t_out, tv->output.result.msg_out);
    497    UNHEX2(expect_keys,
    498           tv->output.state.keys, tv->output.state.nonce);
    499    UNHEX(expect_tprime, tv->output.state.tprime);
    500 
    501    if (tv->inbound) {
    502      cgo_crypt_relay_backward(cgo, &cell);
    503    } else {
    504      const uint8_t *tagp = NULL;
    505      cgo_crypt_relay_forward(cgo, &cell, &tagp);
    506      tt_ptr_op(tagp, OP_EQ, NULL);
    507    }
    508 
    509    tt_mem_op(cell.payload, OP_EQ, expect_cell.payload, sizeof(cell.payload));
    510    tt_mem_op(cgo->uiv.uiv_keys_, OP_EQ, expect_keys, 64);
    511    tt_mem_op(cgo->nonce, OP_EQ, expect_keys + 64, 16);
    512    tt_mem_op(cgo->tprime, OP_EQ, expect_tprime, 16);
    513 
    514    cgo_crypt_free(cgo);
    515  }
    516 done:
    517  tor_free(unhex_tmp);
    518  cgo_crypt_free(cgo);
    519 }
    520 
    521 static void
    522 test_crypto_cgo_relay_originate_testvec(void *arg)
    523 {
    524  (void)arg;
    525  char *unhex_tmp = NULL;
    526  cgo_crypt_t *cgo = NULL;
    527  for (int i = 0; i < (int)ARRAY_LENGTH(CGO_RELAY_ORIGINATE_TESTVECS); ++i) {
    528    const struct cgo_relay_originate_testvec *tv =
    529      &CGO_RELAY_ORIGINATE_TESTVECS[i];
    530    const int aesbits = 128;
    531    uint8_t keys[80], expect_keys[80], expect_tprime[SENDME_TAG_LEN_CGO],
    532      cmd[1];
    533    cell_t cell;
    534    cell_t expect_cell;
    535    tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits));
    536    UNHEX2(keys, tv->state_in.keys, tv->state_in.nonce);
    537    cgo = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD, aesbits, keys, sizeof(keys));
    538    tt_assert(cgo);
    539    UNHEX(cgo->tprime, tv->state_in.tprime);
    540    memset(&cell, 0, sizeof(cell));
    541    UNHEX(cmd, tv->cmd);
    542    cell.command = cmd[0];
    543    UNHEX2(cell.payload, "00000000000000000000000000000000", tv->msg);
    544 
    545    memset(&expect_cell, 0, sizeof(expect_cell));
    546    expect_cell.command = cell.command;
    547    UNHEX2(expect_cell.payload,
    548           tv->output.result.t_out, tv->output.result.msg_out);
    549    UNHEX2(expect_keys,
    550           tv->output.state.keys, tv->output.state.nonce);
    551    UNHEX(expect_tprime, tv->output.state.tprime);
    552 
    553    const uint8_t *tagp = NULL;
    554    cgo_crypt_relay_originate(cgo, &cell, &tagp);
    555    tt_ptr_op(tagp, OP_NE, NULL);
    556 
    557    tt_mem_op(cell.payload, OP_EQ, expect_cell.payload, sizeof(cell.payload));
    558    tt_mem_op(cgo->uiv.uiv_keys_, OP_EQ, expect_keys, 64);
    559    tt_mem_op(cgo->nonce, OP_EQ, expect_keys + 64, 16);
    560    tt_mem_op(cgo->tprime, OP_EQ, expect_tprime, 16);
    561 
    562    cgo_crypt_free(cgo);
    563  }
    564 done:
    565  tor_free(unhex_tmp);
    566  cgo_crypt_free(cgo);
    567 }
    568 
    569 static void
    570 test_crypto_cgo_client_originate_testvec(void *arg)
    571 {
    572  (void) arg;
    573  char *unhex_tmp = NULL;
    574  cgo_crypt_t *cgo[3] = { NULL, NULL, NULL };
    575  for (int tv_i = 0; tv_i < (int)ARRAY_LENGTH(CGO_CLIENT_ORIGINATE_TESTVECS);
    576       ++tv_i) {
    577    const struct cgo_client_originate_testvec *tv =
    578      &CGO_CLIENT_ORIGINATE_TESTVECS[tv_i];
    579    const int aesbits = 128;
    580    uint8_t keys[80], expect_keys[80], expect_tprime[SENDME_TAG_LEN_CGO],
    581      cmd[1];
    582    cell_t cell;
    583    cell_t expect_cell;
    584    for (int i = 0; i < 3; ++i) {
    585      tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits));
    586      UNHEX2(keys, tv->state_in[i].keys, tv->state_in[i].nonce);
    587      cgo[i] = cgo_crypt_new(CGO_MODE_CLIENT_FORWARD,
    588                             aesbits, keys, sizeof(keys));
    589      tt_assert(cgo[i]);
    590      UNHEX(cgo[i]->tprime, tv->state_in[i].tprime);
    591    }
    592 
    593    memset(&cell, 0, sizeof(cell));
    594    UNHEX(cmd, tv->cmd);
    595    cell.command = cmd[0];
    596    UNHEX2(cell.payload, "00000000000000000000000000000000", tv->msg);
    597 
    598    memset(&expect_cell, 0, sizeof(expect_cell));
    599    expect_cell.command = cell.command;
    600    UNHEX2(expect_cell.payload,
    601           tv->output.result.t_out, tv->output.result.msg_out);
    602 
    603    tt_int_op(tv->target_hop, OP_GE, 1); // Hop is 0-indexed.
    604    int target_hop = tv->target_hop - 1;
    605    const uint8_t *tagp = NULL;
    606    cgo_crypt_client_originate(cgo[target_hop], &cell, &tagp);
    607    tt_ptr_op(tagp, OP_NE, NULL);
    608    for (int i = target_hop - 1; i >= 0; --i) {
    609      cgo_crypt_client_forward(cgo[i], &cell);
    610    }
    611    tt_mem_op(cell.payload, OP_EQ, expect_cell.payload, sizeof(cell.payload));
    612 
    613    for (int i = 0; i < 3; ++i) {
    614      UNHEX2(expect_keys,
    615             tv->output.state[i].keys, tv->output.state[i].nonce);
    616      UNHEX(expect_tprime, tv->output.state[i].tprime);
    617 
    618      tt_mem_op(cgo[i]->uiv.uiv_keys_, OP_EQ, expect_keys, 64);
    619      tt_mem_op(cgo[i]->nonce, OP_EQ, expect_keys + 64, 16);
    620      tt_mem_op(cgo[i]->tprime, OP_EQ, expect_tprime, 16);
    621    }
    622 
    623    for (int i = 0; i < 3; ++i)
    624      cgo_crypt_free(cgo[i]);
    625  }
    626 done:
    627  tor_free(unhex_tmp);
    628  for (int i = 0; i < 3; ++i)
    629    cgo_crypt_free(cgo[i]);
    630 }
    631 
    632 struct testcase_t crypto_cgo_tests[] = {
    633  { "et_roundtrip", test_crypto_cgo_et_roundtrip, 0, NULL, NULL },
    634  { "et_testvec", test_crypto_cgo_et_testvec, 0, NULL, NULL },
    635  { "prf_testvec", test_crypto_cgo_prf_testvec, 0, NULL, NULL },
    636  { "uiv_roundtrip", test_crypto_cgo_uiv_roundtrip, 0, NULL, NULL },
    637  { "uiv_testvec", test_crypto_cgo_uiv_testvec, 0, NULL, NULL },
    638  { "uiv_update_testvec", test_crypto_cgo_uiv_update_testvec, 0, NULL, NULL },
    639  { "cgo_fwd", test_crypto_cgo_fwd, 0, NULL, NULL, },
    640  { "cgo_rev", test_crypto_cgo_rev, 0, NULL, NULL, },
    641  { "cgo_relay_testvec", test_crypto_cgo_relay_testvec, 0, NULL, NULL },
    642  { "cgo_relay_originate_testvec", test_crypto_cgo_relay_originate_testvec,
    643    0, NULL, NULL },
    644  { "cgo_client_originate_testvec", test_crypto_cgo_client_originate_testvec,
    645    0, NULL, NULL },
    646  END_OF_TESTCASES
    647 };