xref: /openbsd-src/regress/usr.bin/ssh/unittests/sshkey/test_fuzz.c (revision e5157e49389faebcb42b7237d55fbf096d9c2523)
1 /* 	$OpenBSD: test_fuzz.c,v 1.1 2014/06/24 01:14:18 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_to_blob_buf(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)
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), 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 		sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
85 		    c, sizeof(c), 0);
86 	}
87 	fuzz_cleanup(fuzz);
88 }
89 
90 void
91 sshkey_fuzz_tests(void)
92 {
93 	struct sshkey *k1;
94 	struct sshbuf *buf, *fuzzed;
95 	struct fuzz *fuzz;
96 	int r;
97 
98 	TEST_START("fuzz RSA1 private");
99 	buf = load_file("rsa1_1");
100 	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
101 	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
102 	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
103 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
104 	    &k1, NULL), 0);
105 	sshkey_free(k1);
106 	sshbuf_free(buf);
107 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
108 	TEST_ONERROR(onerror, fuzz);
109 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
110 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
111 		ASSERT_INT_EQ(r, 0);
112 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
113 		    &k1, NULL) == 0)
114 			sshkey_free(k1);
115 		sshbuf_reset(fuzzed);
116 	}
117 	sshbuf_free(fuzzed);
118 	fuzz_cleanup(fuzz);
119 	TEST_DONE();
120 
121 	TEST_START("fuzz RSA1 public");
122 	buf = load_file("rsa1_1_pw");
123 	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
124 	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
125 	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
126 	ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0);
127 	sshkey_free(k1);
128 	sshbuf_free(buf);
129 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
130 	TEST_ONERROR(onerror, fuzz);
131 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
132 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
133 		ASSERT_INT_EQ(r, 0);
134 		if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0)
135 			sshkey_free(k1);
136 		sshbuf_reset(fuzzed);
137 	}
138 	sshbuf_free(fuzzed);
139 	fuzz_cleanup(fuzz);
140 	TEST_DONE();
141 
142 	TEST_START("fuzz RSA private");
143 	buf = load_file("rsa_1");
144 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
145 	    sshbuf_len(buf));
146 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
147 	    &k1, NULL), 0);
148 	sshkey_free(k1);
149 	sshbuf_free(buf);
150 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
151 	TEST_ONERROR(onerror, fuzz);
152 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
153 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
154 		ASSERT_INT_EQ(r, 0);
155 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
156 		    &k1, NULL) == 0)
157 			sshkey_free(k1);
158 		sshbuf_reset(fuzzed);
159 	}
160 	sshbuf_free(fuzzed);
161 	fuzz_cleanup(fuzz);
162 	TEST_DONE();
163 
164 	TEST_START("fuzz RSA new-format private");
165 	buf = load_file("rsa_n");
166 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
167 	    sshbuf_len(buf));
168 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
169 	    &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, "", "key",
178 		    &k1, NULL) == 0)
179 			sshkey_free(k1);
180 		sshbuf_reset(fuzzed);
181 	}
182 	sshbuf_free(fuzzed);
183 	fuzz_cleanup(fuzz);
184 	TEST_DONE();
185 
186 	TEST_START("fuzz DSA private");
187 	buf = load_file("dsa_1");
188 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
189 	    sshbuf_len(buf));
190 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
191 	    &k1, NULL), 0);
192 	sshkey_free(k1);
193 	sshbuf_free(buf);
194 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
195 	TEST_ONERROR(onerror, fuzz);
196 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
197 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
198 		ASSERT_INT_EQ(r, 0);
199 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
200 		    &k1, NULL) == 0)
201 			sshkey_free(k1);
202 		sshbuf_reset(fuzzed);
203 	}
204 	sshbuf_free(fuzzed);
205 	fuzz_cleanup(fuzz);
206 	TEST_DONE();
207 
208 	TEST_START("fuzz DSA new-format private");
209 	buf = load_file("dsa_n");
210 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
211 	    sshbuf_len(buf));
212 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
213 	    &k1, NULL), 0);
214 	sshkey_free(k1);
215 	sshbuf_free(buf);
216 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
217 	TEST_ONERROR(onerror, fuzz);
218 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
219 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
220 		ASSERT_INT_EQ(r, 0);
221 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
222 		    &k1, NULL) == 0)
223 			sshkey_free(k1);
224 		sshbuf_reset(fuzzed);
225 	}
226 	sshbuf_free(fuzzed);
227 	fuzz_cleanup(fuzz);
228 	TEST_DONE();
229 
230 	TEST_START("fuzz ECDSA private");
231 	buf = load_file("ecdsa_1");
232 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
233 	    sshbuf_len(buf));
234 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
235 	    &k1, NULL), 0);
236 	sshkey_free(k1);
237 	sshbuf_free(buf);
238 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
239 	TEST_ONERROR(onerror, fuzz);
240 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
241 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
242 		ASSERT_INT_EQ(r, 0);
243 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
244 		    &k1, NULL) == 0)
245 			sshkey_free(k1);
246 		sshbuf_reset(fuzzed);
247 	}
248 	sshbuf_free(fuzzed);
249 	fuzz_cleanup(fuzz);
250 	TEST_DONE();
251 
252 	TEST_START("fuzz ECDSA new-format private");
253 	buf = load_file("ecdsa_n");
254 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
255 	    sshbuf_len(buf));
256 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
257 	    &k1, NULL), 0);
258 	sshkey_free(k1);
259 	sshbuf_free(buf);
260 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
261 	TEST_ONERROR(onerror, fuzz);
262 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
263 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
264 		ASSERT_INT_EQ(r, 0);
265 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
266 		    &k1, NULL) == 0)
267 			sshkey_free(k1);
268 		sshbuf_reset(fuzzed);
269 	}
270 	sshbuf_free(fuzzed);
271 	fuzz_cleanup(fuzz);
272 	TEST_DONE();
273 
274 	TEST_START("fuzz Ed25519 private");
275 	buf = load_file("ed25519_1");
276 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
277 	    sshbuf_len(buf));
278 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
279 	    &k1, NULL), 0);
280 	sshkey_free(k1);
281 	sshbuf_free(buf);
282 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
283 	TEST_ONERROR(onerror, fuzz);
284 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
285 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
286 		ASSERT_INT_EQ(r, 0);
287 		if (sshkey_parse_private_fileblob(fuzzed, "", "key",
288 		    &k1, NULL) == 0)
289 			sshkey_free(k1);
290 		sshbuf_reset(fuzzed);
291 	}
292 	sshbuf_free(fuzzed);
293 	fuzz_cleanup(fuzz);
294 	TEST_DONE();
295 
296 	TEST_START("fuzz RSA public");
297 	buf = load_file("rsa_1");
298 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
299 	    &k1, NULL), 0);
300 	sshbuf_free(buf);
301 	public_fuzz(k1);
302 	sshkey_free(k1);
303 	TEST_DONE();
304 
305 	TEST_START("fuzz RSA cert");
306 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
307 	public_fuzz(k1);
308 	sshkey_free(k1);
309 	TEST_DONE();
310 
311 	TEST_START("fuzz DSA public");
312 	buf = load_file("dsa_1");
313 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
314 	    &k1, NULL), 0);
315 	sshbuf_free(buf);
316 	public_fuzz(k1);
317 	sshkey_free(k1);
318 	TEST_DONE();
319 
320 	TEST_START("fuzz DSA cert");
321 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
322 	public_fuzz(k1);
323 	sshkey_free(k1);
324 	TEST_DONE();
325 
326 	TEST_START("fuzz ECDSA public");
327 	buf = load_file("ecdsa_1");
328 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
329 	    &k1, NULL), 0);
330 	sshbuf_free(buf);
331 	public_fuzz(k1);
332 	sshkey_free(k1);
333 	TEST_DONE();
334 
335 	TEST_START("fuzz ECDSA cert");
336 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
337 	public_fuzz(k1);
338 	sshkey_free(k1);
339 	TEST_DONE();
340 
341 	TEST_START("fuzz Ed25519 public");
342 	buf = load_file("ed25519_1");
343 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
344 	    &k1, NULL), 0);
345 	sshbuf_free(buf);
346 	public_fuzz(k1);
347 	sshkey_free(k1);
348 	TEST_DONE();
349 
350 	TEST_START("fuzz Ed25519 cert");
351 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
352 	public_fuzz(k1);
353 	sshkey_free(k1);
354 	TEST_DONE();
355 
356 	TEST_START("fuzz RSA sig");
357 	buf = load_file("rsa_1");
358 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
359 	    &k1, NULL), 0);
360 	sshbuf_free(buf);
361 	sig_fuzz(k1);
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, "", "key",
368 	    &k1, NULL), 0);
369 	sshbuf_free(buf);
370 	sig_fuzz(k1);
371 	sshkey_free(k1);
372 	TEST_DONE();
373 
374 	TEST_START("fuzz ECDSA sig");
375 	buf = load_file("ecdsa_1");
376 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
377 	    &k1, NULL), 0);
378 	sshbuf_free(buf);
379 	sig_fuzz(k1);
380 	sshkey_free(k1);
381 	TEST_DONE();
382 
383 	TEST_START("fuzz Ed25519 sig");
384 	buf = load_file("ed25519_1");
385 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
386 	    &k1, NULL), 0);
387 	sshbuf_free(buf);
388 	sig_fuzz(k1);
389 	sshkey_free(k1);
390 	TEST_DONE();
391 
392 /* XXX fuzz decoded new-format blobs too */
393 
394 }
395