1 /*
2 * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com).
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <algorithm>
28 #include <set>
29 #include "../librekey/key_store_pgp.h"
30 #include "pgp-key.h"
31
32 #include "rnp_tests.h"
33 #include "support.h"
34
35 /* This test adds some fake keys to a key store and tests some of
36 * the search functions.
37 */
TEST_F(rnp_tests,test_key_store_search)38 TEST_F(rnp_tests, test_key_store_search)
39 {
40 // create our store
41 rnp_key_store_t *store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx);
42 store->disable_validation = true;
43
44 // some fake key data
45 static const struct {
46 const char *keyid;
47 size_t count; // number of keys like this to add to the store
48 const char *userids[5]; // NULL terminator required on array and strings
49 } testdata[] = {{"000000000000AAAA", 1, {"user1-1", NULL}},
50 {"000000000000BBBB", 2, {"user2", "user1-2", NULL}},
51 {"000000000000CCCC", 1, {"user3", NULL}},
52 {"FFFFFFFFFFFFFFFF", 0, {NULL}}};
53 // add our fake test keys
54 for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) {
55 for (size_t n = 0; n < testdata[i].count; n++) {
56 pgp_key_t key;
57
58 key.pkt().tag = PGP_PKT_PUBLIC_KEY;
59 key.pkt().version = PGP_V4;
60 key.pkt().alg = PGP_PKA_RSA;
61
62 // set the keyid
63 assert_true(rnp::hex_decode(
64 testdata[i].keyid, (uint8_t *) key.keyid().data(), key.keyid().size()));
65 // keys should have different grips otherwise rnp_key_store_add_key will fail here
66 pgp_key_grip_t &grip = (pgp_key_grip_t &) key.grip();
67 assert_true(rnp::hex_decode(testdata[i].keyid, grip.data(), grip.size()));
68 grip[0] = (uint8_t) n;
69 // and fingerprint
70 pgp_fingerprint_t &fp = (pgp_fingerprint_t &) key.fp();
71 assert_true(
72 rnp::hex_decode(testdata[i].keyid, fp.fingerprint, PGP_FINGERPRINT_SIZE));
73 fp.fingerprint[0] = (uint8_t) n;
74 fp.length = PGP_FINGERPRINT_SIZE;
75 // set the userids
76 for (size_t uidn = 0; testdata[i].userids[uidn]; uidn++) {
77 pgp_transferable_userid_t tuid;
78 tuid.uid.tag = PGP_PKT_USER_ID;
79 tuid.uid.uid_len = strlen(testdata[i].userids[uidn]);
80 tuid.uid.uid = (uint8_t *) malloc(tuid.uid.uid_len);
81 assert_non_null(tuid.uid.uid);
82 memcpy(tuid.uid.uid, testdata[i].userids[uidn], tuid.uid.uid_len);
83 key.add_uid(tuid);
84 }
85 // add to the store
86 assert_true(rnp_key_store_add_key(store, &key));
87 }
88 }
89
90 // keyid search
91 for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) {
92 std::string keyid = testdata[i].keyid;
93 std::set<pgp_key_t *> seen_keys;
94 for (pgp_key_t *key = rnp_tests_get_key_by_id(store, keyid); key;
95 key = rnp_tests_get_key_by_id(store, keyid, key)) {
96 // check that the keyid actually matches
97 assert_true(cmp_keyid(key->keyid(), keyid));
98 // check that we have not already encountered this key pointer
99 assert_int_equal(seen_keys.count(key), 0);
100 // keep track of what key pointers we have seen
101 seen_keys.insert(key);
102 }
103 assert_int_equal(seen_keys.size(), testdata[i].count);
104 }
105 // keyid search (by_name)
106 for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) {
107 std::set<pgp_key_t *> seen_keys;
108 pgp_key_t * key = NULL;
109 key = rnp_tests_get_key_by_id(store, testdata[i].keyid);
110 while (key) {
111 // check that the keyid actually matches
112 assert_true(cmp_keyid(key->keyid(), testdata[i].keyid));
113 // check that we have not already encountered this key pointer
114 assert_int_equal(seen_keys.count(key), 0);
115 // keep track of what key pointers we have seen
116 seen_keys.insert(key);
117 // this only returns false on error, regardless of whether it found a match
118 key = rnp_tests_get_key_by_id(store, testdata[i].keyid, key);
119 }
120 // check the count
121 assert_int_equal(seen_keys.size(), testdata[i].count);
122 }
123
124 // userid search (literal)
125 for (auto &key : store->keys) {
126 for (size_t i = 0; i < key.uid_count(); i++) {
127 key.get_uid(i).valid = true;
128 }
129 }
130 for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) {
131 for (size_t uidn = 0; testdata[i].userids[uidn]; uidn++) {
132 std::set<pgp_key_t *> seen_keys;
133 const std::string userid = testdata[i].userids[uidn];
134 pgp_key_t * key = rnp_tests_key_search(store, userid);
135 while (key) {
136 // check that the userid actually matches
137 bool found = false;
138 for (unsigned j = 0; j < key->uid_count(); j++) {
139 if (key->get_uid(j).str == userid) {
140 found = true;
141 }
142 }
143 assert_true(found);
144 // check that we have not already encountered this key pointer
145 assert_int_equal(seen_keys.count(key), 0);
146 // keep track of what key pointers we have seen
147 seen_keys.insert(key);
148 key = rnp_tests_get_key_by_id(store, testdata[i].keyid, key);
149 }
150 // check the count
151 assert_int_equal(seen_keys.size(), testdata[i].count);
152 }
153 }
154
155 // cleanup
156 delete store;
157 }
158
TEST_F(rnp_tests,test_key_store_search_by_name)159 TEST_F(rnp_tests, test_key_store_search_by_name)
160 {
161 const pgp_key_t *key;
162 pgp_key_t * primsec;
163 pgp_key_t * subsec;
164 pgp_key_t * primpub;
165 pgp_key_t * subpub;
166
167 // load pubring
168 rnp_key_store_t *pub_store =
169 new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx);
170 assert_true(rnp_key_store_load_from_path(pub_store, NULL));
171 // load secring
172 rnp_key_store_t *sec_store =
173 new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx);
174 pgp_key_provider_t key_provider = {.callback = rnp_key_provider_store,
175 .userdata = pub_store};
176 assert_true(rnp_key_store_load_from_path(sec_store, &key_provider));
177
178 /* Main key fingerprint and id:
179 4F2E62B74E6A4CD333BC19004BE147BB22DF1E60, 4BE147BB22DF1E60
180 Subkey fingerprint and id:
181 10793E367EE867C32E358F2AA49BAE05C16E8BC8, A49BAE05C16E8BC8
182 */
183
184 /* Find keys and subkeys by fingerprint, id and userid */
185 primsec = rnp_tests_get_key_by_fpr(sec_store, "4F2E62B74E6A4CD333BC19004BE147BB22DF1E60");
186 assert_non_null(primsec);
187 key = rnp_tests_get_key_by_id(sec_store, "4BE147BB22DF1E60");
188 assert_true(key == primsec);
189 subsec = rnp_tests_get_key_by_fpr(sec_store, "10793E367EE867C32E358F2AA49BAE05C16E8BC8");
190 assert_non_null(subsec);
191 assert_true(primsec != subsec);
192 key = rnp_tests_get_key_by_id(sec_store, "A49BAE05C16E8BC8");
193 assert_true(key == subsec);
194
195 primpub = rnp_tests_get_key_by_fpr(pub_store, "4F2E62B74E6A4CD333BC19004BE147BB22DF1E60");
196 assert_non_null(primpub);
197 assert_true(primsec != primpub);
198 subpub = rnp_tests_get_key_by_fpr(pub_store, "10793E367EE867C32E358F2AA49BAE05C16E8BC8");
199 assert_true(primpub != subpub);
200 assert_true(subpub != subsec);
201 key = rnp_tests_key_search(pub_store, "test1");
202 assert_true(key == primpub);
203
204 /* Try other searches */
205 key = rnp_tests_get_key_by_fpr(sec_store, "4f2e62b74e6a4cd333bc19004be147bb22df1e60");
206 assert_true(key == primsec);
207 key = rnp_tests_get_key_by_fpr(sec_store, "0x4f2e62b74e6a4cd333bc19004be147bb22df1e60");
208 assert_true(key == primsec);
209 key = rnp_tests_get_key_by_id(pub_store, "4BE147BB22DF1E60");
210 assert_true(key == primpub);
211 key = rnp_tests_get_key_by_id(pub_store, "4be147bb22df1e60");
212 assert_true(key == primpub);
213 key = rnp_tests_get_key_by_id(pub_store, "0x4be147bb22df1e60");
214 assert_true(key == primpub);
215 key = rnp_tests_get_key_by_id(pub_store, "22df1e60");
216 assert_null(key);
217 key = rnp_tests_get_key_by_id(pub_store, "0x22df1e60");
218 assert_null(key);
219 key = rnp_tests_get_key_by_id(pub_store, "4be1 47bb 22df 1e60");
220 assert_true(key == primpub);
221 key = rnp_tests_get_key_by_id(pub_store, "4be147bb 22df1e60");
222 assert_true(key == primpub);
223 key = rnp_tests_get_key_by_id(pub_store, " 4be147bb\t22df1e60 ");
224 assert_true(key == primpub);
225 key = rnp_tests_get_key_by_id(pub_store, "test1");
226 assert_null(key);
227 /* Try negative searches */
228 assert_null(rnp_tests_get_key_by_fpr(sec_store, "4f2e62b74e6a4cd333bc19004be147bb22df1e"));
229 assert_null(rnp_tests_get_key_by_fpr(sec_store, "2e62b74e6a4cd333bc19004be147bb22df1e60"));
230 assert_null(rnp_tests_get_key_by_id(sec_store, "4be147bb22dfle60"));
231 assert_null(rnp_tests_get_key_by_id(sec_store, ""));
232 assert_null(rnp_tests_get_key_by_id(sec_store, "test11"));
233 assert_null(rnp_tests_get_key_by_id(sec_store, "atest1"));
234
235 // cleanup
236 delete pub_store;
237 delete sec_store;
238 }
239