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