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