1 /*
2 * gnome-keyring
3 *
4 * Copyright (C) 2018 Red Hat, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * Author: Daiki Ueno
21 */
22
23 #include "config.h"
24
25 #include "test-common.h"
26
27 #include "gkd-ssh-agent-private.h"
28 #include "gkd-ssh-agent-util.h"
29 #include "pkcs11/gkm/gkm-mock.h"
30
31 /* RSA private key blob decoded from pkcs11/ssh-store/fixtures/id_rsa_plain */
32 static const guint8 private_blob[4*6 + 0x101 + 0x1 + 0x101 + 0x80 + 0x81 + 0x81] = {
33 /* n */
34 0x00, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x3e, 0x95, 0x2a, 0xa9, 0x21, 0x6b,
35 0x2e, 0xa9, 0x28, 0x74, 0x91, 0x8c, 0x01, 0x96, 0x59, 0xf1, 0x4f, 0x53,
36 0xcc, 0x5f, 0xb2, 0x2d, 0xa0, 0x9c, 0xec, 0x0f, 0xfc, 0x1d, 0x54, 0x1c,
37 0x3a, 0x33, 0xb7, 0x1d, 0xdc, 0xce, 0x13, 0xbe, 0xa7, 0x2f, 0xdf, 0x4e,
38 0x58, 0x42, 0x9d, 0x23, 0xf5, 0x8e, 0xc8, 0xe4, 0xad, 0x52, 0x19, 0x72,
39 0x7c, 0xda, 0x87, 0x67, 0xd4, 0x34, 0x51, 0x51, 0x81, 0x2e, 0x3e, 0x8d,
40 0x13, 0x81, 0xb6, 0xf6, 0xe0, 0x1e, 0xc4, 0xbb, 0xd9, 0x5d, 0x44, 0xeb,
41 0xe6, 0x68, 0x81, 0x5f, 0xa6, 0x04, 0x95, 0x96, 0x02, 0x1c, 0x34, 0x88,
42 0xfa, 0xe6, 0x43, 0x72, 0xaf, 0x9b, 0x7f, 0x03, 0xdc, 0xf0, 0x72, 0xa3,
43 0x96, 0x3b, 0xc8, 0xa3, 0xb9, 0x90, 0x81, 0xb6, 0x2e, 0x5a, 0x18, 0x2e,
44 0x3a, 0x2c, 0x27, 0x91, 0x78, 0xb3, 0x1d, 0xb1, 0x87, 0x4b, 0xb3, 0xdb,
45 0x05, 0xcd, 0xb6, 0x76, 0x35, 0x6f, 0x9c, 0x61, 0x7b, 0x6f, 0x95, 0x12,
46 0x4b, 0x26, 0xf4, 0xe0, 0x7e, 0x15, 0x76, 0x94, 0x91, 0x90, 0xb6, 0x7d,
47 0x0a, 0xd3, 0x36, 0x8f, 0x19, 0x18, 0x52, 0x50, 0x48, 0x57, 0x7c, 0x91,
48 0x48, 0x48, 0x7d, 0xb5, 0x03, 0x26, 0x69, 0x58, 0xb9, 0x9f, 0xaf, 0xbc,
49 0x73, 0x3e, 0x03, 0x72, 0xdc, 0xf6, 0xb1, 0xf2, 0x5b, 0x82, 0x0f, 0x69,
50 0x1c, 0xb1, 0x15, 0x07, 0x22, 0x46, 0x66, 0xfe, 0x65, 0x0a, 0x94, 0xda,
51 0xe4, 0x9d, 0x39, 0x70, 0x21, 0x83, 0x5e, 0xe5, 0xb2, 0x4b, 0x97, 0xfe,
52 0xaf, 0x32, 0x08, 0x8e, 0x47, 0xcb, 0x97, 0x83, 0x89, 0xc0, 0xb6, 0xdb,
53 0x6a, 0x14, 0x31, 0xd2, 0x53, 0xb5, 0x88, 0x30, 0x5f, 0x87, 0x50, 0x09,
54 0x4f, 0x13, 0x20, 0x25, 0xa1, 0xc5, 0xbd, 0xf1, 0xe1, 0x10, 0x95, 0xfa,
55 0x0e, 0xc3, 0xf7, 0xdf, 0xad, 0x90, 0x8b, 0xef, 0xfb,
56 /* e */
57 0x00, 0x00, 0x00, 0x01, 0x23,
58 /* d */
59 0x00, 0x00, 0x01, 0x01, 0x00, 0x9b, 0xaa, 0x82, 0x46, 0xb2, 0xed, 0x43,
60 0x8c, 0x69, 0xcf, 0x87, 0x2e, 0x4d, 0x7d, 0xe2, 0x83, 0x42, 0x2f, 0xcd,
61 0xbf, 0x38, 0x63, 0xf1, 0xcf, 0x39, 0x5a, 0x58, 0xab, 0xc4, 0xb8, 0x1b,
62 0x6b, 0xbd, 0x35, 0x8a, 0xb9, 0x3d, 0x37, 0xc0, 0x85, 0x27, 0x30, 0xb2,
63 0x81, 0x9f, 0xcb, 0xd9, 0xc9, 0xf8, 0x6b, 0x61, 0xcc, 0xf0, 0xab, 0x01,
64 0x80, 0x99, 0xc5, 0x5d, 0x8c, 0x50, 0x14, 0x7b, 0x0f, 0xc6, 0x85, 0xe8,
65 0x21, 0x93, 0xf3, 0x90, 0xbc, 0x75, 0xa9, 0x2b, 0x82, 0xb2, 0x60, 0x35,
66 0x9d, 0xff, 0x1e, 0x97, 0x6e, 0x13, 0x14, 0xf8, 0x1f, 0x4e, 0x99, 0x6f,
67 0x1f, 0x9d, 0xdb, 0x1e, 0xf3, 0xbb, 0x9f, 0xf5, 0x1f, 0xc5, 0x01, 0xa6,
68 0x3a, 0x2b, 0x72, 0x73, 0x29, 0x4a, 0x8c, 0xa2, 0x58, 0xe9, 0xce, 0x58,
69 0xca, 0xcb, 0xce, 0xaa, 0x92, 0x82, 0x1c, 0xd8, 0x57, 0x8b, 0x5e, 0x42,
70 0x79, 0x21, 0x0e, 0x63, 0x13, 0x0e, 0x03, 0xff, 0x2f, 0x7f, 0x64, 0xf6,
71 0x82, 0xe1, 0xfe, 0x0b, 0xc3, 0x1e, 0x4c, 0x50, 0x11, 0x3f, 0xc8, 0x8a,
72 0xba, 0xcc, 0xde, 0x24, 0xf7, 0xae, 0x96, 0x6c, 0x5e, 0x3b, 0x00, 0xfa,
73 0xf0, 0x0e, 0xac, 0x3a, 0xeb, 0xb1, 0xab, 0x8f, 0x3f, 0xdb, 0x80, 0xb3,
74 0x06, 0x91, 0x18, 0xe1, 0xf5, 0x3b, 0xec, 0x5d, 0x01, 0xcf, 0xd0, 0x1f,
75 0xaf, 0xe3, 0xd9, 0x12, 0xba, 0x7b, 0x0f, 0xee, 0x20, 0x29, 0x74, 0x57,
76 0xdc, 0x58, 0x75, 0xd4, 0xb0, 0xf4, 0xb4, 0xa4, 0x93, 0x48, 0x2b, 0x7b,
77 0x6b, 0x1d, 0x77, 0xbc, 0xf3, 0xfe, 0xbd, 0xad, 0xd6, 0x83, 0x05, 0x16,
78 0xca, 0xbe, 0x31, 0xa4, 0x39, 0x53, 0x29, 0xf3, 0xd3, 0x39, 0xb0, 0xa5,
79 0xef, 0xf0, 0xc9, 0x08, 0xd6, 0x63, 0x52, 0x0b, 0xcb, 0xfc, 0x1c, 0x21,
80 0xd3, 0xa9, 0x2f, 0x23, 0x92, 0x3d, 0x46, 0x8c, 0x4b,
81 /* iqmp */
82 0x00, 0x00, 0x00, 0x80, 0x15, 0x40, 0xcc, 0xa4, 0x83, 0xdf, 0x26, 0xbe,
83 0x55, 0x82, 0x85, 0x0f, 0x71, 0x3c, 0x19, 0xa8, 0x8b, 0x42, 0x80, 0xa5,
84 0x24, 0x5d, 0xad, 0xf5, 0x99, 0x33, 0xaf, 0x7c, 0xb2, 0x27, 0xae, 0x7b,
85 0x0b, 0x0b, 0xa0, 0x03, 0xfd, 0xae, 0x53, 0x6f, 0xf1, 0xdd, 0x83, 0x54,
86 0xde, 0xf2, 0xbd, 0x87, 0x2c, 0xa9, 0x4d, 0x7b, 0xa5, 0x6e, 0xdb, 0x5e,
87 0x89, 0xf4, 0x5c, 0x79, 0x22, 0xc3, 0xc4, 0x40, 0x50, 0xeb, 0xb7, 0xf4,
88 0x17, 0x78, 0x2f, 0x06, 0xa5, 0x3a, 0x65, 0x4d, 0x85, 0x98, 0x3e, 0xd8,
89 0x4d, 0x3b, 0xfc, 0xd8, 0x9b, 0xe5, 0xd1, 0x47, 0xb6, 0xe3, 0xda, 0x2e,
90 0xc5, 0x18, 0xce, 0x37, 0xd9, 0xd7, 0x9a, 0xbf, 0xba, 0xa9, 0xef, 0xf2,
91 0xaf, 0x9b, 0xc8, 0x46, 0x57, 0x11, 0x8c, 0xa9, 0x5f, 0x68, 0x8c, 0x43,
92 0x2f, 0xb5, 0x7a, 0x39, 0x38, 0x30, 0x79, 0xd5, 0x30, 0xa8, 0x2b, 0x98,
93 /* p */
94 0x00, 0x00, 0x00, 0x81, 0x00, 0xcc, 0x50, 0xb1, 0x2c, 0x5f, 0xe4, 0x02,
95 0x85, 0x7d, 0xce, 0x77, 0xd8, 0x27, 0xc1, 0xf6, 0xee, 0xe2, 0x2b, 0x7b,
96 0x29, 0x83, 0x95, 0xf1, 0x5e, 0x3d, 0xe5, 0xa9, 0x75, 0x62, 0xc6, 0x84,
97 0xc9, 0x97, 0x26, 0x70, 0xf4, 0x0d, 0x28, 0x6a, 0xc6, 0x88, 0x7c, 0xa3,
98 0x0d, 0x35, 0xa3, 0x8f, 0xdc, 0x34, 0x4c, 0x78, 0x6b, 0xcc, 0x5d, 0x99,
99 0x7e, 0x45, 0xb0, 0xdf, 0xe3, 0x77, 0x48, 0x77, 0xd8, 0xa9, 0x1c, 0x74,
100 0xf9, 0xbc, 0xcc, 0x82, 0xdb, 0x44, 0x10, 0x96, 0xda, 0x00, 0x23, 0xaa,
101 0x04, 0x93, 0xcc, 0x98, 0xec, 0x26, 0x8b, 0x7d, 0x08, 0xf4, 0x82, 0xdc,
102 0x9a, 0xc4, 0x8c, 0xc8, 0xe9, 0x3e, 0x5b, 0xd6, 0xc7, 0x28, 0xf4, 0x38,
103 0x3a, 0x3c, 0x08, 0x56, 0xbb, 0xa2, 0xca, 0xfb, 0x05, 0xa0, 0xb7, 0xe1,
104 0x70, 0x59, 0xb4, 0x86, 0x2b, 0x29, 0x89, 0xb5, 0x82, 0x2a, 0x79, 0x61,
105 0x51,
106 /* q */
107 0x00, 0x00, 0x00, 0x81, 0x00, 0xc8, 0xc7, 0xe6, 0x93, 0x90, 0x59, 0xe7,
108 0x54, 0x1b, 0xcf, 0x9c, 0xb0, 0x07, 0x80, 0x37, 0xcd, 0xdf, 0x65, 0xf4,
109 0x29, 0x1e, 0x4a, 0x93, 0x73, 0xd1, 0x7b, 0x47, 0x1d, 0x36, 0x87, 0x89,
110 0x1d, 0xbf, 0xd5, 0x1e, 0x02, 0xc2, 0xd1, 0x2b, 0xb3, 0x67, 0x07, 0x65,
111 0xf9, 0xbc, 0xcb, 0x74, 0x4c, 0x83, 0x68, 0xa8, 0x6d, 0x30, 0x68, 0x8f,
112 0xb5, 0xb9, 0x44, 0x86, 0xb8, 0xde, 0x4e, 0xfc, 0x02, 0x1e, 0x9c, 0x05,
113 0x3b, 0x23, 0x1b, 0xdf, 0x79, 0x58, 0x73, 0x51, 0x27, 0xf0, 0xbd, 0x83,
114 0x34, 0x38, 0xcb, 0xd0, 0x20, 0x12, 0xcd, 0x1a, 0x07, 0x6e, 0xf7, 0x0a,
115 0x92, 0x29, 0xff, 0x2f, 0xbf, 0x30, 0x2a, 0x69, 0x15, 0x4d, 0x8e, 0x6e,
116 0x17, 0x26, 0x7b, 0x43, 0xfe, 0x52, 0xd1, 0x83, 0x65, 0x19, 0x22, 0x8b,
117 0xd3, 0x6f, 0x97, 0x51, 0x11, 0x3f, 0x17, 0xfe, 0x05, 0xcc, 0xa4, 0x49,
118 0x8b
119 };
120
121 /* define gkd_pkcs11_get_base_functions() for gkd-login.c */
122 CK_FUNCTION_LIST_PTR
123 gkd_pkcs11_get_base_functions (void);
124
125 CK_FUNCTION_LIST_PTR
gkd_pkcs11_get_base_functions(void)126 gkd_pkcs11_get_base_functions (void)
127 {
128 CK_FUNCTION_LIST_PTR funcs;
129 gkm_mock_C_GetFunctionList (&funcs);
130 return funcs;
131 }
132
133 void
prepare_request_identities(EggBuffer * req)134 prepare_request_identities (EggBuffer *req)
135 {
136 gboolean ret;
137
138 egg_buffer_reset (req);
139
140 ret = egg_buffer_add_uint32 (req, 1);
141 g_assert_true (ret);
142
143 ret = egg_buffer_add_byte (req, GKD_SSH_OP_REQUEST_IDENTITIES);
144 g_assert_true (ret);
145 }
146
147 void
check_identities_answer(EggBuffer * resp,gsize count)148 check_identities_answer (EggBuffer *resp, gsize count)
149 {
150 uint32_t length;
151 unsigned char code;
152 size_t offset;
153 gboolean ret;
154
155 offset = 0;
156 ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
157 g_assert_true (ret);
158 g_assert_cmpint (length, ==, resp->len - 4);
159
160 code = 0;
161 ret = egg_buffer_get_byte (resp, offset, &offset, &code);
162 g_assert_true (ret);
163 g_assert_cmpint (code, ==, GKD_SSH_RES_IDENTITIES_ANSWER);
164
165 ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
166 g_assert_true (ret);
167 g_assert_cmpint (length, ==, count);
168 }
169
170 void
prepare_add_identity(EggBuffer * req)171 prepare_add_identity (EggBuffer *req)
172 {
173 gboolean ret;
174
175 egg_buffer_reset (req);
176
177 ret = egg_buffer_add_uint32 (req, 0);
178 g_assert_true (ret);
179
180 ret = egg_buffer_add_byte (req, GKD_SSH_OP_ADD_IDENTITY);
181 g_assert_true (ret);
182
183 ret = egg_buffer_add_string (req, "ssh-rsa");
184 g_assert_true (ret);
185
186 ret = egg_buffer_append (req, private_blob, G_N_ELEMENTS(private_blob));
187 g_assert_true (ret);
188
189 ret = egg_buffer_add_string (req, "comment");
190 g_assert_true (ret);
191
192 ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
193 g_assert_true (ret);
194 }
195
196 GBytes *
public_key_from_file(const gchar * path,gchar ** comment)197 public_key_from_file (const gchar *path, gchar **comment)
198 {
199 GBytes *public_bytes;
200 GBytes *public_key;
201
202 GError *error = NULL;
203 gchar *contents;
204 gsize length;
205
206 if (!g_file_get_contents (path, &contents, &length, &error)) {
207 g_message ("couldn't read file: %s: %s", path, error->message);
208 g_error_free (error);
209 return NULL;
210 }
211
212 public_bytes = g_bytes_new_take (contents, length);
213 public_key = _gkd_ssh_agent_parse_public_key (public_bytes, comment);
214 g_bytes_unref (public_bytes);
215
216 return public_key;
217 }
218
219 void
prepare_remove_identity(EggBuffer * req)220 prepare_remove_identity (EggBuffer *req)
221 {
222 GBytes *public_key;
223 gchar *comment;
224 gsize length;
225 const guchar *blob;
226 gboolean ret;
227
228 public_key = public_key_from_file (SRCDIR "/pkcs11/ssh-store/fixtures/id_rsa_plain.pub", &comment);
229 g_free (comment);
230 blob = g_bytes_get_data (public_key, &length);
231
232 egg_buffer_reset (req);
233 ret = egg_buffer_add_uint32 (req, 0);
234 g_assert_true (ret);
235
236 ret = egg_buffer_add_byte (req, GKD_SSH_OP_REMOVE_IDENTITY);
237 g_assert_true (ret);
238
239 ret = egg_buffer_add_byte_array (req, blob, length);
240 g_assert_true (ret);
241
242 ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
243 g_assert_true (ret);
244
245 g_bytes_unref (public_key);
246 }
247
248 void
prepare_remove_all_identities(EggBuffer * req)249 prepare_remove_all_identities (EggBuffer *req)
250 {
251 gboolean ret;
252
253 egg_buffer_reset (req);
254 ret = egg_buffer_add_uint32 (req, 1);
255 g_assert_true (ret);
256
257 ret = egg_buffer_add_byte (req, GKD_SSH_OP_REMOVE_ALL_IDENTITIES);
258 g_assert_true (ret);
259 }
260
261 void
check_response(EggBuffer * resp,unsigned char expected)262 check_response (EggBuffer *resp, unsigned char expected)
263 {
264 uint32_t length;
265 unsigned char code;
266 size_t offset;
267 gboolean ret;
268
269 offset = 0;
270 ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
271 g_assert_true (ret);
272 g_assert_cmpint (length, ==, resp->len - 4);
273
274 code = 0;
275 ret = egg_buffer_get_byte (resp, offset, &offset, &code);
276 g_assert_true (ret);
277 g_assert_cmpint (expected, ==, code);
278 }
279
280 void
check_success(EggBuffer * resp)281 check_success (EggBuffer *resp)
282 {
283 check_response (resp, GKD_SSH_RES_SUCCESS);
284 }
285
286 void
check_failure(EggBuffer * resp)287 check_failure (EggBuffer *resp)
288 {
289 check_response (resp, GKD_SSH_RES_FAILURE);
290 }
291
292 void
prepare_sign_request(EggBuffer * req)293 prepare_sign_request (EggBuffer *req)
294 {
295 GBytes *public_key;
296 gchar *comment;
297 gsize length;
298 const guchar *blob;
299 gboolean ret;
300
301 public_key = public_key_from_file (SRCDIR "/pkcs11/ssh-store/fixtures/id_rsa_plain.pub", &comment);
302 g_free (comment);
303 blob = g_bytes_get_data (public_key, &length);
304
305 egg_buffer_reset (req);
306 ret = egg_buffer_add_uint32 (req, 0);
307 g_assert_true (ret);
308
309 ret = egg_buffer_add_byte (req, GKD_SSH_OP_SIGN_REQUEST);
310 g_assert_true (ret);
311
312 ret = egg_buffer_add_byte_array (req, blob, length);
313 g_assert_true (ret);
314
315 ret = egg_buffer_add_string (req, "data");
316 g_assert_true (ret);
317
318 ret = egg_buffer_add_uint32 (req, 0);
319 g_assert_true (ret);
320
321 ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
322 g_assert_true (ret);
323
324 g_bytes_unref (public_key);
325 }
326
327 void
check_sign_response(EggBuffer * resp)328 check_sign_response (EggBuffer *resp)
329 {
330 uint32_t length;
331 unsigned char code;
332 size_t offset;
333 gboolean ret;
334
335 offset = 0;
336 ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
337 g_assert_true (ret);
338 g_assert_cmpint (length, ==, resp->len - 4);
339
340 code = 0;
341 ret = egg_buffer_get_byte (resp, offset, &offset, &code);
342 g_assert_true (ret);
343 g_assert_cmpint (code, ==, GKD_SSH_RES_SIGN_RESPONSE);
344
345 ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
346 g_assert_true (ret);
347 }
348