Home | History | Annotate | Download | only in sshkey
      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 
     39 void sshkey_fuzz_tests(void);
     40 
     41 static void
     42 onerror(void *fuzz)
     43 {
     44 	fprintf(stderr, "Failed during fuzz:\n");
     45 	fuzz_dump((struct fuzz *)fuzz);
     46 }
     47 
     48 static void
     49 public_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 
     74 static void
     75 sig_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 
     99 void
    100 sshkey_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