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