test_fuzz.c revision 323134
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 "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, const char *sig_alg)
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), sig_alg, 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, "", &k1, NULL), 0);
114	sshkey_free(k1);
115	sshbuf_free(buf);
116	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
117	TEST_ONERROR(onerror, fuzz);
118	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
119		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
120		ASSERT_INT_EQ(r, 0);
121		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
122			sshkey_free(k1);
123		sshbuf_reset(fuzzed);
124	}
125	sshbuf_free(fuzzed);
126	fuzz_cleanup(fuzz);
127	TEST_DONE();
128
129	TEST_START("fuzz RSA1 public");
130	buf = load_file("rsa1_1_pw");
131	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
132	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
133	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
134	ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0);
135	sshkey_free(k1);
136	sshbuf_free(buf);
137	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
138	TEST_ONERROR(onerror, fuzz);
139	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
140		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
141		ASSERT_INT_EQ(r, 0);
142		if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0)
143			sshkey_free(k1);
144		sshbuf_reset(fuzzed);
145	}
146	sshbuf_free(fuzzed);
147	fuzz_cleanup(fuzz);
148	TEST_DONE();
149#endif
150
151	TEST_START("fuzz RSA private");
152	buf = load_file("rsa_1");
153	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
154	    sshbuf_len(buf));
155	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
156	sshkey_free(k1);
157	sshbuf_free(buf);
158	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
159	TEST_ONERROR(onerror, fuzz);
160	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
161		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
162		ASSERT_INT_EQ(r, 0);
163		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
164			sshkey_free(k1);
165		sshbuf_reset(fuzzed);
166	}
167	sshbuf_free(fuzzed);
168	fuzz_cleanup(fuzz);
169	TEST_DONE();
170
171	TEST_START("fuzz RSA new-format private");
172	buf = load_file("rsa_n");
173	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
174	    sshbuf_len(buf));
175	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
176	sshkey_free(k1);
177	sshbuf_free(buf);
178	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
179	TEST_ONERROR(onerror, fuzz);
180	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
181		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
182		ASSERT_INT_EQ(r, 0);
183		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
184			sshkey_free(k1);
185		sshbuf_reset(fuzzed);
186	}
187	sshbuf_free(fuzzed);
188	fuzz_cleanup(fuzz);
189	TEST_DONE();
190
191	TEST_START("fuzz DSA private");
192	buf = load_file("dsa_1");
193	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
194	    sshbuf_len(buf));
195	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
196	sshkey_free(k1);
197	sshbuf_free(buf);
198	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
199	TEST_ONERROR(onerror, fuzz);
200	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
201		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
202		ASSERT_INT_EQ(r, 0);
203		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
204			sshkey_free(k1);
205		sshbuf_reset(fuzzed);
206	}
207	sshbuf_free(fuzzed);
208	fuzz_cleanup(fuzz);
209	TEST_DONE();
210
211	TEST_START("fuzz DSA new-format private");
212	buf = load_file("dsa_n");
213	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
214	    sshbuf_len(buf));
215	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
216	sshkey_free(k1);
217	sshbuf_free(buf);
218	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
219	TEST_ONERROR(onerror, fuzz);
220	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
221		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
222		ASSERT_INT_EQ(r, 0);
223		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
224			sshkey_free(k1);
225		sshbuf_reset(fuzzed);
226	}
227	sshbuf_free(fuzzed);
228	fuzz_cleanup(fuzz);
229	TEST_DONE();
230
231#ifdef OPENSSL_HAS_ECC
232	TEST_START("fuzz ECDSA private");
233	buf = load_file("ecdsa_1");
234	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
235	    sshbuf_len(buf));
236	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
237	sshkey_free(k1);
238	sshbuf_free(buf);
239	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
240	TEST_ONERROR(onerror, fuzz);
241	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
242		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
243		ASSERT_INT_EQ(r, 0);
244		if (sshkey_parse_private_fileblob(fuzzed, "", &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, "", &k1, NULL), 0);
257	sshkey_free(k1);
258	sshbuf_free(buf);
259	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
260	TEST_ONERROR(onerror, fuzz);
261	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
262		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
263		ASSERT_INT_EQ(r, 0);
264		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
265			sshkey_free(k1);
266		sshbuf_reset(fuzzed);
267	}
268	sshbuf_free(fuzzed);
269	fuzz_cleanup(fuzz);
270	TEST_DONE();
271#endif
272
273	TEST_START("fuzz Ed25519 private");
274	buf = load_file("ed25519_1");
275	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
276	    sshbuf_len(buf));
277	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
278	sshkey_free(k1);
279	sshbuf_free(buf);
280	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
281	TEST_ONERROR(onerror, fuzz);
282	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
283		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
284		ASSERT_INT_EQ(r, 0);
285		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
286			sshkey_free(k1);
287		sshbuf_reset(fuzzed);
288	}
289	sshbuf_free(fuzzed);
290	fuzz_cleanup(fuzz);
291	TEST_DONE();
292
293	TEST_START("fuzz RSA public");
294	buf = load_file("rsa_1");
295	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
296	sshbuf_free(buf);
297	public_fuzz(k1);
298	sshkey_free(k1);
299	TEST_DONE();
300
301	TEST_START("fuzz RSA cert");
302	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
303	public_fuzz(k1);
304	sshkey_free(k1);
305	TEST_DONE();
306
307	TEST_START("fuzz DSA public");
308	buf = load_file("dsa_1");
309	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
310	sshbuf_free(buf);
311	public_fuzz(k1);
312	sshkey_free(k1);
313	TEST_DONE();
314
315	TEST_START("fuzz DSA cert");
316	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
317	public_fuzz(k1);
318	sshkey_free(k1);
319	TEST_DONE();
320
321#ifdef OPENSSL_HAS_ECC
322	TEST_START("fuzz ECDSA public");
323	buf = load_file("ecdsa_1");
324	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
325	sshbuf_free(buf);
326	public_fuzz(k1);
327	sshkey_free(k1);
328	TEST_DONE();
329
330	TEST_START("fuzz ECDSA cert");
331	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
332	public_fuzz(k1);
333	sshkey_free(k1);
334	TEST_DONE();
335#endif
336
337	TEST_START("fuzz Ed25519 public");
338	buf = load_file("ed25519_1");
339	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
340	sshbuf_free(buf);
341	public_fuzz(k1);
342	sshkey_free(k1);
343	TEST_DONE();
344
345	TEST_START("fuzz Ed25519 cert");
346	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
347	public_fuzz(k1);
348	sshkey_free(k1);
349	TEST_DONE();
350
351	TEST_START("fuzz RSA sig");
352	buf = load_file("rsa_1");
353	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
354	sshbuf_free(buf);
355	sig_fuzz(k1, "ssh-rsa");
356	sshkey_free(k1);
357	TEST_DONE();
358
359	TEST_START("fuzz RSA SHA256 sig");
360	buf = load_file("rsa_1");
361	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
362	sshbuf_free(buf);
363	sig_fuzz(k1, "rsa-sha2-256");
364	sshkey_free(k1);
365	TEST_DONE();
366
367	TEST_START("fuzz RSA SHA512 sig");
368	buf = load_file("rsa_1");
369	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
370	sshbuf_free(buf);
371	sig_fuzz(k1, "rsa-sha2-512");
372	sshkey_free(k1);
373	TEST_DONE();
374
375	TEST_START("fuzz DSA sig");
376	buf = load_file("dsa_1");
377	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
378	sshbuf_free(buf);
379	sig_fuzz(k1, NULL);
380	sshkey_free(k1);
381	TEST_DONE();
382
383#ifdef OPENSSL_HAS_ECC
384	TEST_START("fuzz ECDSA sig");
385	buf = load_file("ecdsa_1");
386	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
387	sshbuf_free(buf);
388	sig_fuzz(k1, NULL);
389	sshkey_free(k1);
390	TEST_DONE();
391#endif
392
393	TEST_START("fuzz Ed25519 sig");
394	buf = load_file("ed25519_1");
395	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
396	sshbuf_free(buf);
397	sig_fuzz(k1, NULL);
398	sshkey_free(k1);
399	TEST_DONE();
400
401/* XXX fuzz decoded new-format blobs too */
402
403}
404