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 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) 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 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, "", "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