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