xref: /openbsd-src/regress/usr.bin/ssh/unittests/sshkey/test_fuzz.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* 	$OpenBSD: test_fuzz.c,v 1.6 2015/12/07 02:20:46 djm Exp $ */
2 /*
3  * Fuzz tests for key parsing
4  *
5  * Placed in the public domain
6  */
7 
8 #include <sys/types.h>
9 #include <sys/param.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 
18 #include <openssl/bn.h>
19 #include <openssl/ec.h>
20 #include <openssl/rsa.h>
21 #include <openssl/dsa.h>
22 #include <openssl/objects.h>
23 
24 #include "test_helper.h"
25 
26 #include "ssherr.h"
27 #include "authfile.h"
28 #include "sshkey.h"
29 #include "sshbuf.h"
30 
31 #include "common.h"
32 
33 void sshkey_fuzz_tests(void);
34 
35 static void
36 onerror(void *fuzz)
37 {
38 	fprintf(stderr, "Failed during fuzz:\n");
39 	fuzz_dump((struct fuzz *)fuzz);
40 }
41 
42 static void
43 public_fuzz(struct sshkey *k)
44 {
45 	struct sshkey *k1;
46 	struct sshbuf *buf;
47 	struct fuzz *fuzz;
48 
49 	ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
50 	ASSERT_INT_EQ(sshkey_putb(k, buf), 0);
51 	/* XXX need a way to run the tests in "slow, but complete" mode */
52 	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */
53 	    FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */
54 	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
55 	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
56 	ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf),
57 	    &k1), 0);
58 	sshkey_free(k1);
59 	sshbuf_free(buf);
60 	TEST_ONERROR(onerror, fuzz);
61 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
62 		if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0)
63 			sshkey_free(k1);
64 	}
65 	fuzz_cleanup(fuzz);
66 }
67 
68 static void
69 sig_fuzz(struct sshkey *k, const char *sig_alg)
70 {
71 	struct fuzz *fuzz;
72 	u_char *sig, c[] = "some junk to be signed";
73 	size_t l;
74 
75 	ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), sig_alg, 0), 0);
76 	ASSERT_SIZE_T_GT(l, 0);
77 	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* too slow FUZZ_2_BIT_FLIP | */
78 	    FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
79 	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sig, l);
80 	ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), 0), 0);
81 	free(sig);
82 	TEST_ONERROR(onerror, fuzz);
83 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
84 		/* Ensure 1-bit difference at least */
85 		if (fuzz_matches_original(fuzz))
86 			continue;
87 		ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
88 		    c, sizeof(c), 0), 0);
89 	}
90 	fuzz_cleanup(fuzz);
91 }
92 
93 void
94 sshkey_fuzz_tests(void)
95 {
96 	struct sshkey *k1;
97 	struct sshbuf *buf, *fuzzed;
98 	struct fuzz *fuzz;
99 	int r;
100 
101 #ifdef WITH_SSH1
102 	TEST_START("fuzz RSA1 private");
103 	buf = load_file("rsa1_1");
104 	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
105 	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
106 	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
107 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
108 	sshkey_free(k1);
109 	sshbuf_free(buf);
110 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
111 	TEST_ONERROR(onerror, fuzz);
112 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
113 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
114 		ASSERT_INT_EQ(r, 0);
115 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
116 			sshkey_free(k1);
117 		sshbuf_reset(fuzzed);
118 	}
119 	sshbuf_free(fuzzed);
120 	fuzz_cleanup(fuzz);
121 	TEST_DONE();
122 
123 	TEST_START("fuzz RSA1 public");
124 	buf = load_file("rsa1_1_pw");
125 	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
126 	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
127 	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
128 	ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0);
129 	sshkey_free(k1);
130 	sshbuf_free(buf);
131 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
132 	TEST_ONERROR(onerror, fuzz);
133 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
134 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
135 		ASSERT_INT_EQ(r, 0);
136 		if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0)
137 			sshkey_free(k1);
138 		sshbuf_reset(fuzzed);
139 	}
140 	sshbuf_free(fuzzed);
141 	fuzz_cleanup(fuzz);
142 	TEST_DONE();
143 #endif
144 
145 	TEST_START("fuzz RSA private");
146 	buf = load_file("rsa_1");
147 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
148 	    sshbuf_len(buf));
149 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
150 	sshkey_free(k1);
151 	sshbuf_free(buf);
152 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
153 	TEST_ONERROR(onerror, fuzz);
154 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
155 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
156 		ASSERT_INT_EQ(r, 0);
157 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
158 			sshkey_free(k1);
159 		sshbuf_reset(fuzzed);
160 	}
161 	sshbuf_free(fuzzed);
162 	fuzz_cleanup(fuzz);
163 	TEST_DONE();
164 
165 	TEST_START("fuzz RSA new-format private");
166 	buf = load_file("rsa_n");
167 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
168 	    sshbuf_len(buf));
169 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
170 	sshkey_free(k1);
171 	sshbuf_free(buf);
172 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
173 	TEST_ONERROR(onerror, fuzz);
174 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
175 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
176 		ASSERT_INT_EQ(r, 0);
177 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
178 			sshkey_free(k1);
179 		sshbuf_reset(fuzzed);
180 	}
181 	sshbuf_free(fuzzed);
182 	fuzz_cleanup(fuzz);
183 	TEST_DONE();
184 
185 	TEST_START("fuzz DSA private");
186 	buf = load_file("dsa_1");
187 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
188 	    sshbuf_len(buf));
189 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
190 	sshkey_free(k1);
191 	sshbuf_free(buf);
192 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
193 	TEST_ONERROR(onerror, fuzz);
194 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
195 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
196 		ASSERT_INT_EQ(r, 0);
197 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
198 			sshkey_free(k1);
199 		sshbuf_reset(fuzzed);
200 	}
201 	sshbuf_free(fuzzed);
202 	fuzz_cleanup(fuzz);
203 	TEST_DONE();
204 
205 	TEST_START("fuzz DSA new-format private");
206 	buf = load_file("dsa_n");
207 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
208 	    sshbuf_len(buf));
209 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
210 	sshkey_free(k1);
211 	sshbuf_free(buf);
212 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
213 	TEST_ONERROR(onerror, fuzz);
214 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
215 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
216 		ASSERT_INT_EQ(r, 0);
217 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
218 			sshkey_free(k1);
219 		sshbuf_reset(fuzzed);
220 	}
221 	sshbuf_free(fuzzed);
222 	fuzz_cleanup(fuzz);
223 	TEST_DONE();
224 
225 	TEST_START("fuzz ECDSA private");
226 	buf = load_file("ecdsa_1");
227 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
228 	    sshbuf_len(buf));
229 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
230 	sshkey_free(k1);
231 	sshbuf_free(buf);
232 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
233 	TEST_ONERROR(onerror, fuzz);
234 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
235 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
236 		ASSERT_INT_EQ(r, 0);
237 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
238 			sshkey_free(k1);
239 		sshbuf_reset(fuzzed);
240 	}
241 	sshbuf_free(fuzzed);
242 	fuzz_cleanup(fuzz);
243 	TEST_DONE();
244 
245 	TEST_START("fuzz ECDSA new-format private");
246 	buf = load_file("ecdsa_n");
247 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
248 	    sshbuf_len(buf));
249 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
250 	sshkey_free(k1);
251 	sshbuf_free(buf);
252 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
253 	TEST_ONERROR(onerror, fuzz);
254 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
255 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
256 		ASSERT_INT_EQ(r, 0);
257 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
258 			sshkey_free(k1);
259 		sshbuf_reset(fuzzed);
260 	}
261 	sshbuf_free(fuzzed);
262 	fuzz_cleanup(fuzz);
263 	TEST_DONE();
264 
265 	TEST_START("fuzz Ed25519 private");
266 	buf = load_file("ed25519_1");
267 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
268 	    sshbuf_len(buf));
269 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
270 	sshkey_free(k1);
271 	sshbuf_free(buf);
272 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
273 	TEST_ONERROR(onerror, fuzz);
274 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
275 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
276 		ASSERT_INT_EQ(r, 0);
277 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
278 			sshkey_free(k1);
279 		sshbuf_reset(fuzzed);
280 	}
281 	sshbuf_free(fuzzed);
282 	fuzz_cleanup(fuzz);
283 	TEST_DONE();
284 
285 	TEST_START("fuzz RSA public");
286 	buf = load_file("rsa_1");
287 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
288 	sshbuf_free(buf);
289 	public_fuzz(k1);
290 	sshkey_free(k1);
291 	TEST_DONE();
292 
293 	TEST_START("fuzz RSA cert");
294 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
295 	public_fuzz(k1);
296 	sshkey_free(k1);
297 	TEST_DONE();
298 
299 	TEST_START("fuzz DSA public");
300 	buf = load_file("dsa_1");
301 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
302 	sshbuf_free(buf);
303 	public_fuzz(k1);
304 	sshkey_free(k1);
305 	TEST_DONE();
306 
307 	TEST_START("fuzz DSA cert");
308 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
309 	public_fuzz(k1);
310 	sshkey_free(k1);
311 	TEST_DONE();
312 
313 	TEST_START("fuzz ECDSA public");
314 	buf = load_file("ecdsa_1");
315 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
316 	sshbuf_free(buf);
317 	public_fuzz(k1);
318 	sshkey_free(k1);
319 	TEST_DONE();
320 
321 	TEST_START("fuzz ECDSA cert");
322 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
323 	public_fuzz(k1);
324 	sshkey_free(k1);
325 	TEST_DONE();
326 
327 	TEST_START("fuzz Ed25519 public");
328 	buf = load_file("ed25519_1");
329 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
330 	sshbuf_free(buf);
331 	public_fuzz(k1);
332 	sshkey_free(k1);
333 	TEST_DONE();
334 
335 	TEST_START("fuzz Ed25519 cert");
336 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
337 	public_fuzz(k1);
338 	sshkey_free(k1);
339 	TEST_DONE();
340 
341 	TEST_START("fuzz RSA sig");
342 	buf = load_file("rsa_1");
343 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
344 	sshbuf_free(buf);
345 	sig_fuzz(k1, "ssh-rsa");
346 	sshkey_free(k1);
347 	TEST_DONE();
348 
349 	TEST_START("fuzz RSA SHA256 sig");
350 	buf = load_file("rsa_1");
351 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
352 	sshbuf_free(buf);
353 	sig_fuzz(k1, "rsa-sha2-256");
354 	sshkey_free(k1);
355 	TEST_DONE();
356 
357 	TEST_START("fuzz RSA SHA512 sig");
358 	buf = load_file("rsa_1");
359 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
360 	sshbuf_free(buf);
361 	sig_fuzz(k1, "rsa-sha2-512");
362 	sshkey_free(k1);
363 	TEST_DONE();
364 
365 	TEST_START("fuzz DSA sig");
366 	buf = load_file("dsa_1");
367 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
368 	sshbuf_free(buf);
369 	sig_fuzz(k1, NULL);
370 	sshkey_free(k1);
371 	TEST_DONE();
372 
373 	TEST_START("fuzz ECDSA sig");
374 	buf = load_file("ecdsa_1");
375 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
376 	sshbuf_free(buf);
377 	sig_fuzz(k1, NULL);
378 	sshkey_free(k1);
379 	TEST_DONE();
380 
381 	TEST_START("fuzz Ed25519 sig");
382 	buf = load_file("ed25519_1");
383 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
384 	sshbuf_free(buf);
385 	sig_fuzz(k1, NULL);
386 	sshkey_free(k1);
387 	TEST_DONE();
388 
389 /* XXX fuzz decoded new-format blobs too */
390 
391 }
392