1296781Sdes/* $OpenBSD: test_fuzz.c,v 1.6 2015/12/07 02:20:46 djm Exp $ */ 2276707Sdes/* 3276707Sdes * Fuzz tests for key parsing 4276707Sdes * 5276707Sdes * Placed in the public domain 6276707Sdes */ 7276707Sdes 8276707Sdes#include "includes.h" 9276707Sdes 10276707Sdes#include <sys/types.h> 11276707Sdes#include <sys/param.h> 12276707Sdes#include <sys/stat.h> 13276707Sdes#include <fcntl.h> 14276707Sdes#include <stdio.h> 15276707Sdes#ifdef HAVE_STDINT_H 16276707Sdes#include <stdint.h> 17276707Sdes#endif 18276707Sdes#include <stdlib.h> 19276707Sdes#include <string.h> 20276707Sdes#include <unistd.h> 21276707Sdes 22276707Sdes#include <openssl/bn.h> 23276707Sdes#include <openssl/rsa.h> 24276707Sdes#include <openssl/dsa.h> 25276707Sdes#include <openssl/objects.h> 26276707Sdes#ifdef OPENSSL_HAS_NISTP256 27276707Sdes# include <openssl/ec.h> 28276707Sdes#endif 29276707Sdes 30276707Sdes#include "../test_helper/test_helper.h" 31276707Sdes 32276707Sdes#include "ssherr.h" 33276707Sdes#include "authfile.h" 34276707Sdes#include "sshkey.h" 35276707Sdes#include "sshbuf.h" 36276707Sdes 37276707Sdes#include "common.h" 38276707Sdes 39276707Sdesvoid sshkey_fuzz_tests(void); 40276707Sdes 41276707Sdesstatic void 42276707Sdesonerror(void *fuzz) 43276707Sdes{ 44276707Sdes fprintf(stderr, "Failed during fuzz:\n"); 45276707Sdes fuzz_dump((struct fuzz *)fuzz); 46276707Sdes} 47276707Sdes 48276707Sdesstatic void 49276707Sdespublic_fuzz(struct sshkey *k) 50276707Sdes{ 51276707Sdes struct sshkey *k1; 52276707Sdes struct sshbuf *buf; 53276707Sdes struct fuzz *fuzz; 54276707Sdes 55276707Sdes ASSERT_PTR_NE(buf = sshbuf_new(), NULL); 56295367Sdes ASSERT_INT_EQ(sshkey_putb(k, buf), 0); 57276707Sdes /* XXX need a way to run the tests in "slow, but complete" mode */ 58276707Sdes fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */ 59276707Sdes FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */ 60276707Sdes FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, 61276707Sdes sshbuf_mutable_ptr(buf), sshbuf_len(buf)); 62276707Sdes ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf), 63276707Sdes &k1), 0); 64276707Sdes sshkey_free(k1); 65276707Sdes sshbuf_free(buf); 66276707Sdes TEST_ONERROR(onerror, fuzz); 67276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 68276707Sdes if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0) 69276707Sdes sshkey_free(k1); 70276707Sdes } 71276707Sdes fuzz_cleanup(fuzz); 72276707Sdes} 73276707Sdes 74276707Sdesstatic void 75296781Sdessig_fuzz(struct sshkey *k, const char *sig_alg) 76276707Sdes{ 77276707Sdes struct fuzz *fuzz; 78276707Sdes u_char *sig, c[] = "some junk to be signed"; 79276707Sdes size_t l; 80276707Sdes 81296781Sdes ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), sig_alg, 0), 0); 82276707Sdes ASSERT_SIZE_T_GT(l, 0); 83276707Sdes fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* too slow FUZZ_2_BIT_FLIP | */ 84276707Sdes FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | 85276707Sdes FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sig, l); 86276707Sdes ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), 0), 0); 87276707Sdes free(sig); 88276707Sdes TEST_ONERROR(onerror, fuzz); 89276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 90295367Sdes /* Ensure 1-bit difference at least */ 91295367Sdes if (fuzz_matches_original(fuzz)) 92295367Sdes continue; 93295367Sdes ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), 94295367Sdes c, sizeof(c), 0), 0); 95276707Sdes } 96276707Sdes fuzz_cleanup(fuzz); 97276707Sdes} 98276707Sdes 99276707Sdesvoid 100276707Sdessshkey_fuzz_tests(void) 101276707Sdes{ 102276707Sdes struct sshkey *k1; 103276707Sdes struct sshbuf *buf, *fuzzed; 104276707Sdes struct fuzz *fuzz; 105276707Sdes int r; 106276707Sdes 107295367Sdes#ifdef WITH_SSH1 108276707Sdes TEST_START("fuzz RSA1 private"); 109276707Sdes buf = load_file("rsa1_1"); 110276707Sdes fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | 111276707Sdes FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, 112276707Sdes sshbuf_mutable_ptr(buf), sshbuf_len(buf)); 113296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 114276707Sdes sshkey_free(k1); 115276707Sdes sshbuf_free(buf); 116276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 117276707Sdes TEST_ONERROR(onerror, fuzz); 118276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 119276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 120276707Sdes ASSERT_INT_EQ(r, 0); 121296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 122276707Sdes sshkey_free(k1); 123276707Sdes sshbuf_reset(fuzzed); 124276707Sdes } 125276707Sdes sshbuf_free(fuzzed); 126276707Sdes fuzz_cleanup(fuzz); 127276707Sdes TEST_DONE(); 128276707Sdes 129276707Sdes TEST_START("fuzz RSA1 public"); 130276707Sdes buf = load_file("rsa1_1_pw"); 131276707Sdes fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | 132276707Sdes FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, 133276707Sdes sshbuf_mutable_ptr(buf), sshbuf_len(buf)); 134276707Sdes ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0); 135276707Sdes sshkey_free(k1); 136276707Sdes sshbuf_free(buf); 137276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 138276707Sdes TEST_ONERROR(onerror, fuzz); 139276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 140276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 141276707Sdes ASSERT_INT_EQ(r, 0); 142276707Sdes if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0) 143276707Sdes sshkey_free(k1); 144276707Sdes sshbuf_reset(fuzzed); 145276707Sdes } 146276707Sdes sshbuf_free(fuzzed); 147276707Sdes fuzz_cleanup(fuzz); 148276707Sdes TEST_DONE(); 149295367Sdes#endif 150276707Sdes 151276707Sdes TEST_START("fuzz RSA private"); 152276707Sdes buf = load_file("rsa_1"); 153276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 154276707Sdes sshbuf_len(buf)); 155296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 156276707Sdes sshkey_free(k1); 157276707Sdes sshbuf_free(buf); 158276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 159276707Sdes TEST_ONERROR(onerror, fuzz); 160276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 161276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 162276707Sdes ASSERT_INT_EQ(r, 0); 163296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 164276707Sdes sshkey_free(k1); 165276707Sdes sshbuf_reset(fuzzed); 166276707Sdes } 167276707Sdes sshbuf_free(fuzzed); 168276707Sdes fuzz_cleanup(fuzz); 169276707Sdes TEST_DONE(); 170276707Sdes 171276707Sdes TEST_START("fuzz RSA new-format private"); 172276707Sdes buf = load_file("rsa_n"); 173276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 174276707Sdes sshbuf_len(buf)); 175296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 176276707Sdes sshkey_free(k1); 177276707Sdes sshbuf_free(buf); 178276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 179276707Sdes TEST_ONERROR(onerror, fuzz); 180276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 181276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 182276707Sdes ASSERT_INT_EQ(r, 0); 183296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 184276707Sdes sshkey_free(k1); 185276707Sdes sshbuf_reset(fuzzed); 186276707Sdes } 187276707Sdes sshbuf_free(fuzzed); 188276707Sdes fuzz_cleanup(fuzz); 189276707Sdes TEST_DONE(); 190276707Sdes 191276707Sdes TEST_START("fuzz DSA private"); 192276707Sdes buf = load_file("dsa_1"); 193276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 194276707Sdes sshbuf_len(buf)); 195296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 196276707Sdes sshkey_free(k1); 197276707Sdes sshbuf_free(buf); 198276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 199276707Sdes TEST_ONERROR(onerror, fuzz); 200276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 201276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 202276707Sdes ASSERT_INT_EQ(r, 0); 203296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 204276707Sdes sshkey_free(k1); 205276707Sdes sshbuf_reset(fuzzed); 206276707Sdes } 207276707Sdes sshbuf_free(fuzzed); 208276707Sdes fuzz_cleanup(fuzz); 209276707Sdes TEST_DONE(); 210276707Sdes 211276707Sdes TEST_START("fuzz DSA new-format private"); 212276707Sdes buf = load_file("dsa_n"); 213276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 214276707Sdes sshbuf_len(buf)); 215296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 216276707Sdes sshkey_free(k1); 217276707Sdes sshbuf_free(buf); 218276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 219276707Sdes TEST_ONERROR(onerror, fuzz); 220276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 221276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 222276707Sdes ASSERT_INT_EQ(r, 0); 223296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 224276707Sdes sshkey_free(k1); 225276707Sdes sshbuf_reset(fuzzed); 226276707Sdes } 227276707Sdes sshbuf_free(fuzzed); 228276707Sdes fuzz_cleanup(fuzz); 229276707Sdes TEST_DONE(); 230276707Sdes 231276707Sdes#ifdef OPENSSL_HAS_ECC 232276707Sdes TEST_START("fuzz ECDSA private"); 233276707Sdes buf = load_file("ecdsa_1"); 234276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 235276707Sdes sshbuf_len(buf)); 236296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 237276707Sdes sshkey_free(k1); 238276707Sdes sshbuf_free(buf); 239276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 240276707Sdes TEST_ONERROR(onerror, fuzz); 241276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 242276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 243276707Sdes ASSERT_INT_EQ(r, 0); 244296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 245276707Sdes sshkey_free(k1); 246276707Sdes sshbuf_reset(fuzzed); 247276707Sdes } 248276707Sdes sshbuf_free(fuzzed); 249276707Sdes fuzz_cleanup(fuzz); 250276707Sdes TEST_DONE(); 251276707Sdes 252276707Sdes TEST_START("fuzz ECDSA new-format private"); 253276707Sdes buf = load_file("ecdsa_n"); 254276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 255276707Sdes sshbuf_len(buf)); 256296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 257276707Sdes sshkey_free(k1); 258276707Sdes sshbuf_free(buf); 259276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 260276707Sdes TEST_ONERROR(onerror, fuzz); 261276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 262276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 263276707Sdes ASSERT_INT_EQ(r, 0); 264296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 265276707Sdes sshkey_free(k1); 266276707Sdes sshbuf_reset(fuzzed); 267276707Sdes } 268276707Sdes sshbuf_free(fuzzed); 269276707Sdes fuzz_cleanup(fuzz); 270276707Sdes TEST_DONE(); 271276707Sdes#endif 272276707Sdes 273276707Sdes TEST_START("fuzz Ed25519 private"); 274276707Sdes buf = load_file("ed25519_1"); 275276707Sdes fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), 276276707Sdes sshbuf_len(buf)); 277296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 278276707Sdes sshkey_free(k1); 279276707Sdes sshbuf_free(buf); 280276707Sdes ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); 281276707Sdes TEST_ONERROR(onerror, fuzz); 282276707Sdes for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 283276707Sdes r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); 284276707Sdes ASSERT_INT_EQ(r, 0); 285296781Sdes if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) 286276707Sdes sshkey_free(k1); 287276707Sdes sshbuf_reset(fuzzed); 288276707Sdes } 289276707Sdes sshbuf_free(fuzzed); 290276707Sdes fuzz_cleanup(fuzz); 291276707Sdes TEST_DONE(); 292276707Sdes 293276707Sdes TEST_START("fuzz RSA public"); 294276707Sdes buf = load_file("rsa_1"); 295296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 296276707Sdes sshbuf_free(buf); 297276707Sdes public_fuzz(k1); 298276707Sdes sshkey_free(k1); 299276707Sdes TEST_DONE(); 300276707Sdes 301276707Sdes TEST_START("fuzz RSA cert"); 302276707Sdes ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); 303276707Sdes public_fuzz(k1); 304276707Sdes sshkey_free(k1); 305276707Sdes TEST_DONE(); 306276707Sdes 307276707Sdes TEST_START("fuzz DSA public"); 308276707Sdes buf = load_file("dsa_1"); 309296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 310276707Sdes sshbuf_free(buf); 311276707Sdes public_fuzz(k1); 312276707Sdes sshkey_free(k1); 313276707Sdes TEST_DONE(); 314276707Sdes 315276707Sdes TEST_START("fuzz DSA cert"); 316276707Sdes ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); 317276707Sdes public_fuzz(k1); 318276707Sdes sshkey_free(k1); 319276707Sdes TEST_DONE(); 320276707Sdes 321276707Sdes#ifdef OPENSSL_HAS_ECC 322276707Sdes TEST_START("fuzz ECDSA public"); 323276707Sdes buf = load_file("ecdsa_1"); 324296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 325276707Sdes sshbuf_free(buf); 326276707Sdes public_fuzz(k1); 327276707Sdes sshkey_free(k1); 328276707Sdes TEST_DONE(); 329276707Sdes 330276707Sdes TEST_START("fuzz ECDSA cert"); 331276707Sdes ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0); 332276707Sdes public_fuzz(k1); 333276707Sdes sshkey_free(k1); 334276707Sdes TEST_DONE(); 335276707Sdes#endif 336276707Sdes 337276707Sdes TEST_START("fuzz Ed25519 public"); 338276707Sdes buf = load_file("ed25519_1"); 339296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 340276707Sdes sshbuf_free(buf); 341276707Sdes public_fuzz(k1); 342276707Sdes sshkey_free(k1); 343276707Sdes TEST_DONE(); 344276707Sdes 345276707Sdes TEST_START("fuzz Ed25519 cert"); 346276707Sdes ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0); 347276707Sdes public_fuzz(k1); 348276707Sdes sshkey_free(k1); 349276707Sdes TEST_DONE(); 350276707Sdes 351276707Sdes TEST_START("fuzz RSA sig"); 352276707Sdes buf = load_file("rsa_1"); 353296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 354276707Sdes sshbuf_free(buf); 355296781Sdes sig_fuzz(k1, "ssh-rsa"); 356276707Sdes sshkey_free(k1); 357276707Sdes TEST_DONE(); 358276707Sdes 359296781Sdes TEST_START("fuzz RSA SHA256 sig"); 360296781Sdes buf = load_file("rsa_1"); 361296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 362296781Sdes sshbuf_free(buf); 363296781Sdes sig_fuzz(k1, "rsa-sha2-256"); 364296781Sdes sshkey_free(k1); 365296781Sdes TEST_DONE(); 366296781Sdes 367296781Sdes TEST_START("fuzz RSA SHA512 sig"); 368296781Sdes buf = load_file("rsa_1"); 369296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 370296781Sdes sshbuf_free(buf); 371296781Sdes sig_fuzz(k1, "rsa-sha2-512"); 372296781Sdes sshkey_free(k1); 373296781Sdes TEST_DONE(); 374296781Sdes 375276707Sdes TEST_START("fuzz DSA sig"); 376276707Sdes buf = load_file("dsa_1"); 377296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 378276707Sdes sshbuf_free(buf); 379296781Sdes sig_fuzz(k1, NULL); 380276707Sdes sshkey_free(k1); 381276707Sdes TEST_DONE(); 382276707Sdes 383276707Sdes#ifdef OPENSSL_HAS_ECC 384276707Sdes TEST_START("fuzz ECDSA sig"); 385276707Sdes buf = load_file("ecdsa_1"); 386296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 387276707Sdes sshbuf_free(buf); 388296781Sdes sig_fuzz(k1, NULL); 389276707Sdes sshkey_free(k1); 390276707Sdes TEST_DONE(); 391276707Sdes#endif 392276707Sdes 393276707Sdes TEST_START("fuzz Ed25519 sig"); 394276707Sdes buf = load_file("ed25519_1"); 395296781Sdes ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 396276707Sdes sshbuf_free(buf); 397296781Sdes sig_fuzz(k1, NULL); 398276707Sdes sshkey_free(k1); 399276707Sdes TEST_DONE(); 400276707Sdes 401276707Sdes/* XXX fuzz decoded new-format blobs too */ 402276707Sdes 403276707Sdes} 404