Merge branch 'maint-0.4.8'
[tor.git] / src / test / test_keypin.c
blob7b73e94b3ace060ba197820da356e1ed8507381c
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #include "orconfig.h"
5 #define KEYPIN_PRIVATE
6 #include "core/or/or.h"
7 #include "feature/dirauth/keypin.h"
9 #include "test/test.h"
11 static void
12 test_keypin_parse_line(void *arg)
14 (void)arg;
15 keypin_ent_t *ent = NULL;
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;
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;
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);
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);
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);
53 done:
54 tor_free(ent);
57 static smartlist_t *mock_addent_got = NULL;
58 static void
59 mock_addent(keypin_ent_t *ent)
61 smartlist_add(mock_addent_got, ent);
62 keypin_add_entry_to_map__real(ent);
65 static void
66 test_keypin_parse_file(void *arg)
68 (void)arg;
70 mock_addent_got = smartlist_new();
71 MOCK(keypin_add_entry_to_map, mock_addent);
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";
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);
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"
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);
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);
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);
129 done:
130 keypin_clear();
131 smartlist_free(mock_addent_got);
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))
138 static void
139 test_keypin_add_entry(void *arg)
141 (void)arg;
142 keypin_clear();
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"));
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"));
156 tt_int_op(KEYPIN_ADDED, OP_EQ, ADD("Johnnies-come-lately",
157 "run-of-the-mill root-mean-square"));
159 tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("gentleman-adventurer",
160 "hypersentimental closefistedness"));
162 tt_int_op(KEYPIN_MISMATCH, OP_EQ, ADD("disestablismentarian",
163 "cloak-and-dagger what's-his-face"));
165 tt_int_op(KEYPIN_FOUND, OP_EQ, ADD("gentleman-adventurer",
166 "cloak-and-dagger what's-his-face"));
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"));
171 done:
172 keypin_clear();
175 static void
176 test_keypin_journal(void *arg)
178 (void)arg;
179 char *contents = NULL;
180 const char *fname = get_fname("keypin-journal");
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));
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();
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();
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();
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");
238 done:
239 tor_free(contents);
240 keypin_clear();
243 #undef ADD
244 #undef LONE_RSA
246 #define TEST(name, flags) \
247 { #name , test_keypin_ ## name, (flags), NULL, NULL }
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