tor

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

test_keypin.c (9939B)


      1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 #include "orconfig.h"
      5 #define KEYPIN_PRIVATE
      6 #include "core/or/or.h"
      7 #include "feature/dirauth/keypin.h"
      8 
      9 #include "test/test.h"
     10 
     11 static void
     12 test_keypin_parse_line(void *arg)
     13 {
     14  (void)arg;
     15  keypin_ent_t *ent = NULL;
     16 
     17  /* Good line */
     18  ent = keypin_parse_journal_line(
     19                "aGVyZSBpcyBhIGdvb2Qgc2hhMSE "
     20                "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4");
     21  tt_assert(ent);
     22  tt_mem_op(ent->rsa_id, OP_EQ, "here is a good sha1!", 20);
     23  tt_mem_op(ent->ed25519_key, OP_EQ, "This ed25519 scoffs at the sha1.", 32);
     24  tor_free(ent); ent = NULL;
     25 
     26  /* Good line with extra stuff we will ignore. */
     27  ent = keypin_parse_journal_line(
     28                "aGVyZSBpcyBhIGdvb2Qgc2hhMSE "
     29                "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4helloworld");
     30  tt_assert(ent);
     31  tt_mem_op(ent->rsa_id, OP_EQ, "here is a good sha1!", 20);
     32  tt_mem_op(ent->ed25519_key, OP_EQ, "This ed25519 scoffs at the sha1.", 32);
     33  tor_free(ent); ent = NULL;
     34 
     35  /* Bad line: no space in the middle. */
     36  ent = keypin_parse_journal_line(
     37                "aGVyZSBpcyBhIGdvb2Qgc2hhMSE?"
     38                "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4");
     39  tt_ptr_op(ent, OP_EQ, NULL);
     40 
     41  /* Bad line: bad base64 in RSA ID */
     42  ent = keypin_parse_journal_line(
     43                "aGVyZSBpcyBhIGdv!2Qgc2hhMSE "
     44                "VGhpcyBlZDI1NTE5IHNjb2ZmcyBhdCB0aGUgc2hhMS4");
     45  tt_ptr_op(ent, OP_EQ, NULL);
     46 
     47  /* Bad line: bad base64 in Ed25519 */
     48  ent = keypin_parse_journal_line(
     49                "aGVyZSBpcyBhIGdvb2Qgc2hhMSE "
     50                "VGhpcyBlZDI1NTE5IHNjb2ZmcyB!dCB0aGUgc2hhMS4");
     51  tt_ptr_op(ent, OP_EQ, NULL);
     52 
     53 done:
     54  tor_free(ent);
     55 }
     56 
     57 static smartlist_t *mock_addent_got = NULL;
     58 static void
     59 mock_addent(keypin_ent_t *ent)
     60 {
     61  smartlist_add(mock_addent_got, ent);
     62  keypin_add_entry_to_map__real(ent);
     63 }
     64 
     65 static void
     66 test_keypin_parse_file(void *arg)
     67 {
     68  (void)arg;
     69 
     70  mock_addent_got = smartlist_new();
     71  MOCK(keypin_add_entry_to_map, mock_addent);
     72 
     73  /* Simple, minimal, correct example. */
     74  const char data1[] =
     75 "PT09PT09PT09PT09PT09PT09PT0 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0\n"
     76 "TG9yYXggaXBzdW0gZ3J1dnZ1bHU cyB0aG5lZWQgYW1ldCwgc25lcmdlbGx5IG9uY2UtbGU\n"
     77 "ciBsZXJraW0sIHNlZCBkbyBiYXI YmFsb290IHRlbXBvciBnbHVwcGl0dXMgdXQgbGFib3I\n"
     78 "ZSBldCB0cnVmZnVsYSBtYWduYSA YWxpcXVhLiBVdCBlbmltIGFkIGdyaWNrbGUtZ3Jhc3M\n"
     79 "dmVuaWFtLCBxdWlzIG1pZmYtbXU ZmZlcmVkIGdhLXp1bXBjbyBsYWJvcmlzIG5pc2kgdXQ\n"
     80 "Y3J1ZmZ1bHVzIGV4IGVhIHNjaGw b3BwaXR5IGNvbnNlcXVhdC4gRHVpcyBhdXRlIHNuYXI\n"
     81 "Z2dsZSBpbiBzd29tZWVzd2FucyA aW4gdm9sdXB0YXRlIGF4ZS1oYWNrZXIgZXNzZSByaXA\n"
     82 "cHVsdXMgY3J1bW1paSBldSBtb28 ZiBudWxsYSBzbnV2di5QTFVHSFBMT1ZFUlhZWlpZLi4\n";
     83 
     84  tt_int_op(0, OP_EQ, keypin_load_journal_impl(data1, strlen(data1)));
     85  tt_int_op(8, OP_EQ, smartlist_len(mock_addent_got));
     86  keypin_ent_t *ent = smartlist_get(mock_addent_got, 2);
     87  tt_mem_op(ent->rsa_id, OP_EQ, "r lerkim, sed do bar", 20);
     88  tt_mem_op(ent->ed25519_key, OP_EQ, "baloot tempor gluppitus ut labor", 32);
     89 
     90  /* More complex example: weird lines, bogus lines,
     91     duplicate/conflicting lines */
     92  const char data2[] =
     93    "PT09PT09PT09PT09PT09PT09PT0 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0\n"
     94    "# This is a comment.\n"
     95    "     \n"
     96    "QXQgdGhlIGVuZCBvZiB0aGUgeWU YXIgS3VycmVta2FybWVycnVrIHNhaWQgdG8gaGltLCA\n"
     97    "IllvdSBoYXZlIG1hZGUgYSBnb28 ZCBiZWdpbm5pbmcuIiBCdXQgbm8gbW9yZS4gV2l6YXI\n"
     98    "\n"
     99    "ZHMgc3BlYWsgdHJ1dGgsIGFuZCA aXQgd2FzIHRydWUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n"
    100    "@reserved for a future extension \n"
    101    "eSBvZiBOYW1lcyB0aGF0IEdlZCA aGFkIHRvaWxlZCbyB3aW4gdGhhdCB5ZWFyIHdhcyA\n"
    102    "eSBvZiBOYW1lcyB0aGF0IEdlZCA aGFkIHRvaWxlZCbyB3aW4gdGhhdCB5ZWFyIHdhcy"
    103              "A line too long\n"
    104    "dGhlIG1lcmUgc3RhcnQgb2Ygd2g YXQgaGUgbXVzdCBnbyBvb!BsZWFybmluZy4uLi4uLi4\n"
    105    "ZHMgc3BlYWsgdaJ1dGgsIGFuZCA aXQgd2FzIHRydWUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n"
    106    "ZHMgc3BlYWsgdHJ1dGgsIGFuZCA aXQgd2FzIHRydaUgdGhhdCBhbGwgdGhlIG1hc3Rlcgo\n"
    107    ;
    108 
    109  tt_int_op(0, OP_EQ, keypin_load_journal_impl(data2, strlen(data2)));
    110  tt_int_op(13, OP_EQ, smartlist_len(mock_addent_got));
    111  ent = smartlist_get(mock_addent_got, 9);
    112  tt_mem_op(ent->rsa_id, OP_EQ, "\"You have made a goo", 20);
    113  tt_mem_op(ent->ed25519_key, OP_EQ, "d beginning.\" But no more. Wizar", 32);
    114 
    115  ent = smartlist_get(mock_addent_got, 12);
    116  tt_mem_op(ent->rsa_id, OP_EQ, "ds speak truth, and ", 20);
    117  tt_mem_op(ent->ed25519_key, OP_EQ,
    118            "it was tru\xa5 that all the master\n", 32);
    119 
    120  /* File truncated before NL */
    121  const char data3[] =
    122    "Tm8gZHJhZ29uIGNhbiByZXNpc3Q IHRoZSBmYXNjaW5hdGlvbiBvZiByaWRkbGluZyB0YWw";
    123  tt_int_op(0, OP_EQ, keypin_load_journal_impl(data3, strlen(data3)));
    124  tt_int_op(14, OP_EQ, smartlist_len(mock_addent_got));
    125  ent = smartlist_get(mock_addent_got, 13);
    126  tt_mem_op(ent->rsa_id, OP_EQ, "No dragon can resist", 20);
    127  tt_mem_op(ent->ed25519_key, OP_EQ, " the fascination of riddling tal", 32);
    128 
    129 done:
    130  keypin_clear();
    131  smartlist_free(mock_addent_got);
    132 }
    133 
    134 #define ADD(a,b) keypin_check_and_add((const uint8_t*)(a),\
    135                                      (const uint8_t*)(b),0)
    136 #define LONE_RSA(a) keypin_check_lone_rsa((const uint8_t*)(a))
    137 
    138 static void
    139 test_keypin_add_entry(void *arg)
    140 {
    141  (void)arg;
    142  keypin_clear();
    143 
    144  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("ambassadors-at-large",
    145                                  "bread-and-butter thing-in-itself"));
    146  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("gentleman-adventurer",
    147                                  "cloak-and-dagger what's-his-face"));
    148 
    149  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("ambassadors-at-large",
    150                                  "bread-and-butter thing-in-itself"));
    151  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("ambassadors-at-large",
    152                                  "bread-and-butter thing-in-itself"));
    153  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer",
    154                                  "cloak-and-dagger what's-his-face"));
    155 
    156  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("Johnnies-come-lately",
    157                                  "run-of-the-mill root-mean-square"));
    158 
    159  tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("gentleman-adventurer",
    160                                     "hypersentimental closefistedness"));
    161 
    162  tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("disestablismentarian",
    163                                     "cloak-and-dagger what's-his-face"));
    164 
    165  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer",
    166                                  "cloak-and-dagger what's-his-face"));
    167 
    168  tt_int_op(KEYPIN_NOT_FOUND, OP_EQ, LONE_RSA("Llanfairpwllgwyngyll"));
    169  tt_int_op(KEYPIN_MISMATCH, OP_EQ, LONE_RSA("Johnnies-come-lately"));
    170 
    171 done:
    172  keypin_clear();
    173 }
    174 
    175 static void
    176 test_keypin_journal(void *arg)
    177 {
    178  (void)arg;
    179  char *contents = NULL;
    180  const char *fname = get_fname("keypin-journal");
    181 
    182  tt_int_op(0, OP_EQ, keypin_load_journal(fname)); /* ENOENT is okay */
    183  update_approx_time(1217709000);
    184  tt_int_op(0, OP_EQ, keypin_open_journal(fname));
    185 
    186  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("king-of-the-herrings",
    187                                  "good-for-nothing attorney-at-law"));
    188  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("yellowish-red-yellow",
    189                                  "salt-and-pepper high-muck-a-muck"));
    190  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow",
    191                                  "salt-and-pepper high-muck-a-muck"));
    192  keypin_close_journal();
    193  keypin_clear();
    194 
    195  tt_int_op(0, OP_EQ, keypin_load_journal(fname));
    196  update_approx_time(1231041600);
    197  tt_int_op(0, OP_EQ, keypin_open_journal(fname));
    198  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow",
    199                                  "salt-and-pepper high-muck-a-muck"));
    200  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("theatre-in-the-round",
    201                                  "holier-than-thou jack-in-the-box"));
    202  tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("no-deposit-no-return",
    203                                  "across-the-board will-o-the-wisp"));
    204  tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("intellectualizations",
    205                                     "salt-and-pepper high-muck-a-muck"));
    206  keypin_close_journal();
    207  keypin_clear();
    208 
    209  tt_int_op(0, OP_EQ, keypin_load_journal(fname));
    210  update_approx_time(1412278354);
    211  tt_int_op(0, OP_EQ, keypin_open_journal(fname));
    212  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("yellowish-red-yellow",
    213                                  "salt-and-pepper high-muck-a-muck"));
    214  tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("intellectualizations",
    215                                     "salt-and-pepper high-muck-a-muck"));
    216  tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("theatre-in-the-round",
    217                                  "holier-than-thou jack-in-the-box"));
    218  tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("counterrevolutionary",
    219                                     "holier-than-thou jack-in-the-box"));
    220  tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("no-deposit-no-return",
    221                                     "floccinaucinihilipilificationism"));
    222  keypin_close_journal();
    223 
    224  contents = read_file_to_str(fname, RFTS_BIN, NULL);
    225  tt_assert(contents);
    226  tt_str_op(contents,OP_EQ,
    227    "\n"
    228    "@opened-at 2008-08-02 20:30:00\n"
    229    "a2luZy1vZi10aGUtaGVycmluZ3M Z29vZC1mb3Itbm90aGluZyBhdHRvcm5leS1hdC1sYXc\n"
    230    "eWVsbG93aXNoLXJlZC15ZWxsb3c c2FsdC1hbmQtcGVwcGVyIGhpZ2gtbXVjay1hLW11Y2s\n"
    231    "\n"
    232    "@opened-at 2009-01-04 04:00:00\n"
    233    "dGhlYXRyZS1pbi10aGUtcm91bmQ aG9saWVyLXRoYW4tdGhvdSBqYWNrLWluLXRoZS1ib3g\n"
    234    "bm8tZGVwb3NpdC1uby1yZXR1cm4 YWNyb3NzLXRoZS1ib2FyZCB3aWxsLW8tdGhlLXdpc3A\n"
    235    "\n"
    236    "@opened-at 2014-10-02 19:32:34\n");
    237 
    238 done:
    239  tor_free(contents);
    240  keypin_clear();
    241 }
    242 
    243 #undef ADD
    244 #undef LONE_RSA
    245 
    246 #define TEST(name, flags)                                       \
    247  { #name , test_keypin_ ## name, (flags), NULL, NULL }
    248 
    249 struct testcase_t keypin_tests[] = {
    250  TEST( parse_line, 0 ),
    251  TEST( parse_file, TT_FORK ),
    252  TEST( add_entry, TT_FORK ),
    253  TEST( journal, TT_FORK ),
    254  END_OF_TESTCASES
    255 };