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