xref: /openbsd-src/regress/usr.bin/ssh/unittests/sshkey/test_fuzz.c (revision 897fc685943471cf985a0fe38ba076ea6fe74fa5)
1 /* 	$OpenBSD: test_fuzz.c,v 1.8 2017/12/21 00:41:22 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), NULL, 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), NULL, 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 
102 	TEST_START("fuzz RSA private");
103 	buf = load_file("rsa_1");
104 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
105 	    sshbuf_len(buf));
106 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
107 	sshkey_free(k1);
108 	sshbuf_free(buf);
109 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
110 	TEST_ONERROR(onerror, fuzz);
111 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
112 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
113 		ASSERT_INT_EQ(r, 0);
114 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
115 			sshkey_free(k1);
116 		sshbuf_reset(fuzzed);
117 	}
118 	sshbuf_free(fuzzed);
119 	fuzz_cleanup(fuzz);
120 	TEST_DONE();
121 
122 	TEST_START("fuzz RSA new-format private");
123 	buf = load_file("rsa_n");
124 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
125 	    sshbuf_len(buf));
126 	ASSERT_INT_EQ(sshkey_parse_private_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_private_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 DSA private");
143 	buf = load_file("dsa_1");
144 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
145 	    sshbuf_len(buf));
146 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
147 	sshkey_free(k1);
148 	sshbuf_free(buf);
149 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
150 	TEST_ONERROR(onerror, fuzz);
151 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
152 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
153 		ASSERT_INT_EQ(r, 0);
154 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
155 			sshkey_free(k1);
156 		sshbuf_reset(fuzzed);
157 	}
158 	sshbuf_free(fuzzed);
159 	fuzz_cleanup(fuzz);
160 	TEST_DONE();
161 
162 	TEST_START("fuzz DSA new-format private");
163 	buf = load_file("dsa_n");
164 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
165 	    sshbuf_len(buf));
166 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
167 	sshkey_free(k1);
168 	sshbuf_free(buf);
169 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
170 	TEST_ONERROR(onerror, fuzz);
171 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
172 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
173 		ASSERT_INT_EQ(r, 0);
174 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
175 			sshkey_free(k1);
176 		sshbuf_reset(fuzzed);
177 	}
178 	sshbuf_free(fuzzed);
179 	fuzz_cleanup(fuzz);
180 	TEST_DONE();
181 
182 	TEST_START("fuzz ECDSA private");
183 	buf = load_file("ecdsa_1");
184 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
185 	    sshbuf_len(buf));
186 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
187 	sshkey_free(k1);
188 	sshbuf_free(buf);
189 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
190 	TEST_ONERROR(onerror, fuzz);
191 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
192 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
193 		ASSERT_INT_EQ(r, 0);
194 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
195 			sshkey_free(k1);
196 		sshbuf_reset(fuzzed);
197 	}
198 	sshbuf_free(fuzzed);
199 	fuzz_cleanup(fuzz);
200 	TEST_DONE();
201 
202 	TEST_START("fuzz ECDSA new-format private");
203 	buf = load_file("ecdsa_n");
204 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
205 	    sshbuf_len(buf));
206 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
207 	sshkey_free(k1);
208 	sshbuf_free(buf);
209 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
210 	TEST_ONERROR(onerror, fuzz);
211 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
212 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
213 		ASSERT_INT_EQ(r, 0);
214 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
215 			sshkey_free(k1);
216 		sshbuf_reset(fuzzed);
217 	}
218 	sshbuf_free(fuzzed);
219 	fuzz_cleanup(fuzz);
220 	TEST_DONE();
221 
222 	TEST_START("fuzz Ed25519 private");
223 	buf = load_file("ed25519_1");
224 	fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
225 	    sshbuf_len(buf));
226 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
227 	sshkey_free(k1);
228 	sshbuf_free(buf);
229 	ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
230 	TEST_ONERROR(onerror, fuzz);
231 	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
232 		r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
233 		ASSERT_INT_EQ(r, 0);
234 		if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
235 			sshkey_free(k1);
236 		sshbuf_reset(fuzzed);
237 	}
238 	sshbuf_free(fuzzed);
239 	fuzz_cleanup(fuzz);
240 	TEST_DONE();
241 
242 	TEST_START("fuzz RSA public");
243 	buf = load_file("rsa_1");
244 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
245 	sshbuf_free(buf);
246 	public_fuzz(k1);
247 	sshkey_free(k1);
248 	TEST_DONE();
249 
250 	TEST_START("fuzz RSA cert");
251 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
252 	public_fuzz(k1);
253 	sshkey_free(k1);
254 	TEST_DONE();
255 
256 	TEST_START("fuzz DSA public");
257 	buf = load_file("dsa_1");
258 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
259 	sshbuf_free(buf);
260 	public_fuzz(k1);
261 	sshkey_free(k1);
262 	TEST_DONE();
263 
264 	TEST_START("fuzz DSA cert");
265 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
266 	public_fuzz(k1);
267 	sshkey_free(k1);
268 	TEST_DONE();
269 
270 	TEST_START("fuzz ECDSA public");
271 	buf = load_file("ecdsa_1");
272 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
273 	sshbuf_free(buf);
274 	public_fuzz(k1);
275 	sshkey_free(k1);
276 	TEST_DONE();
277 
278 	TEST_START("fuzz ECDSA cert");
279 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
280 	public_fuzz(k1);
281 	sshkey_free(k1);
282 	TEST_DONE();
283 
284 	TEST_START("fuzz Ed25519 public");
285 	buf = load_file("ed25519_1");
286 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
287 	sshbuf_free(buf);
288 	public_fuzz(k1);
289 	sshkey_free(k1);
290 	TEST_DONE();
291 
292 	TEST_START("fuzz Ed25519 cert");
293 	ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
294 	public_fuzz(k1);
295 	sshkey_free(k1);
296 	TEST_DONE();
297 
298 	TEST_START("fuzz RSA sig");
299 	buf = load_file("rsa_1");
300 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
301 	sshbuf_free(buf);
302 	sig_fuzz(k1, "ssh-rsa");
303 	sshkey_free(k1);
304 	TEST_DONE();
305 
306 	TEST_START("fuzz RSA SHA256 sig");
307 	buf = load_file("rsa_1");
308 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
309 	sshbuf_free(buf);
310 	sig_fuzz(k1, "rsa-sha2-256");
311 	sshkey_free(k1);
312 	TEST_DONE();
313 
314 	TEST_START("fuzz RSA SHA512 sig");
315 	buf = load_file("rsa_1");
316 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
317 	sshbuf_free(buf);
318 	sig_fuzz(k1, "rsa-sha2-512");
319 	sshkey_free(k1);
320 	TEST_DONE();
321 
322 	TEST_START("fuzz DSA sig");
323 	buf = load_file("dsa_1");
324 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
325 	sshbuf_free(buf);
326 	sig_fuzz(k1, NULL);
327 	sshkey_free(k1);
328 	TEST_DONE();
329 
330 	TEST_START("fuzz ECDSA sig");
331 	buf = load_file("ecdsa_1");
332 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
333 	sshbuf_free(buf);
334 	sig_fuzz(k1, NULL);
335 	sshkey_free(k1);
336 	TEST_DONE();
337 
338 	TEST_START("fuzz Ed25519 sig");
339 	buf = load_file("ed25519_1");
340 	ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
341 	sshbuf_free(buf);
342 	sig_fuzz(k1, NULL);
343 	sshkey_free(k1);
344 	TEST_DONE();
345 
346 /* XXX fuzz decoded new-format blobs too */
347 
348 }
349