From 982279b366eccd9e4146036c7fcda7f72d2cbdff Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Tue, 15 May 2018 18:44:57 -0400 Subject: [PATCH] Add a PKCS#12 fuzzer. Change-Id: Iee3a3d46d283bd6cbb46940e630916aacdd71db6 Reviewed-on: https://boringssl-review.googlesource.com/28552 Reviewed-by: Adam Langley Commit-Queue: David Benjamin CQ-Verified: CQ bot account: commit-bot@chromium.org --- crypto/pkcs8/pkcs12_test.cc | 6 + crypto/pkcs8/pkcs8_x509.c | 3 + fuzz/CMakeLists.txt | 139 ++++-------------- fuzz/pkcs12.cc | 29 ++++ .../04191202c1f7d978bcb3a4c1316d88b046689e31 | Bin 0 -> 2567 bytes .../7dbf598a00e4d22ac2ae1bc658fbc6596901d53f | Bin 0 -> 2636 bytes .../aab806b45129f3284cf9598951cdd57a86e63ab5 | Bin 0 -> 2469 bytes .../fff673b3287ad0d26ffa212d14d94ce2d015c7ab | Bin 0 -> 2566 bytes 8 files changed, 66 insertions(+), 111 deletions(-) create mode 100644 fuzz/pkcs12.cc create mode 100644 fuzz/pkcs12_corpus/04191202c1f7d978bcb3a4c1316d88b046689e31 create mode 100644 fuzz/pkcs12_corpus/7dbf598a00e4d22ac2ae1bc658fbc6596901d53f create mode 100644 fuzz/pkcs12_corpus/aab806b45129f3284cf9598951cdd57a86e63ab5 create mode 100644 fuzz/pkcs12_corpus/fff673b3287ad0d26ffa212d14d94ce2d015c7ab diff --git a/crypto/pkcs8/pkcs12_test.cc b/crypto/pkcs8/pkcs12_test.cc index 5fb7903a..e6c0e56b 100644 --- a/crypto/pkcs8/pkcs12_test.cc +++ b/crypto/pkcs8/pkcs12_test.cc @@ -1234,11 +1234,17 @@ TEST(PKCS12Test, TestPBES2) { } TEST(PKCS12Test, TestEmptyPassword) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + return; // The MAC check always passes in fuzzer mode. +#endif TestImpl("EmptyPassword (empty password)", kEmptyPassword, "", nullptr); TestImpl("EmptyPassword (null password)", kEmptyPassword, nullptr, nullptr); } TEST(PKCS12Test, TestNullPassword) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + return; // The MAC check always passes in fuzzer mode. +#endif TestImpl("NullPassword (empty password)", kNullPassword, "", nullptr); TestImpl("NullPassword (null password)", kNullPassword, nullptr, nullptr); } diff --git a/crypto/pkcs8/pkcs8_x509.c b/crypto/pkcs8/pkcs8_x509.c index 3cdbddb9..23aad09f 100644 --- a/crypto/pkcs8/pkcs8_x509.c +++ b/crypto/pkcs8/pkcs8_x509.c @@ -573,6 +573,9 @@ static int pkcs12_check_mac(int *out_mac_ok, const char *password, } *out_mac_ok = CBS_mem_equal(expected_mac, hmac, hmac_len); +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + *out_mac_ok = 1; +#endif ret = 1; err: diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index eddb38c5..a2696961 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -2,127 +2,44 @@ include_directories(../include) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-prototypes") -add_executable( - bn_mod_exp +add_executable(bn_mod_exp bn_mod_exp.cc) +target_link_libraries(bn_mod_exp Fuzzer crypto) - bn_mod_exp.cc -) +add_executable(bn_div bn_div.cc) +target_link_libraries(bn_div Fuzzer crypto) -target_link_libraries(bn_mod_exp Fuzzer) -target_link_libraries(bn_mod_exp crypto) +add_executable(privkey privkey.cc) +target_link_libraries(privkey Fuzzer crypto) -add_executable( - bn_div +add_executable(cert cert.cc) +target_link_libraries(cert Fuzzer crypto) - bn_div.cc -) +add_executable(spki spki.cc) +target_link_libraries(spki Fuzzer crypto) -target_link_libraries(bn_div Fuzzer) -target_link_libraries(bn_div crypto) +add_executable(pkcs8 pkcs8.cc) +target_link_libraries(pkcs8 Fuzzer crypto) -add_executable( - privkey +add_executable(pkcs12 pkcs12.cc) +target_link_libraries(pkcs12 Fuzzer crypto) - privkey.cc -) +add_executable(server server.cc) +target_link_libraries(server Fuzzer crypto ssl) -target_link_libraries(privkey Fuzzer) -target_link_libraries(privkey crypto) +add_executable(client client.cc) +target_link_libraries(client Fuzzer crypto ssl) -add_executable( - cert +add_executable(dtls_server dtls_server.cc) +target_link_libraries(dtls_server Fuzzer crypto ssl) - cert.cc -) +add_executable(dtls_client dtls_client.cc) +target_link_libraries(dtls_client Fuzzer crypto ssl) -target_link_libraries(cert Fuzzer) -target_link_libraries(cert crypto) +add_executable(read_pem read_pem.cc) +target_link_libraries(read_pem Fuzzer crypto) -add_executable( - spki +add_executable(ssl_ctx_api ssl_ctx_api.cc) +target_link_libraries(ssl_ctx_api Fuzzer crypto ssl) - spki.cc -) - -target_link_libraries(spki Fuzzer) -target_link_libraries(spki crypto) - -add_executable( - pkcs8 - - pkcs8.cc -) - -target_link_libraries(pkcs8 Fuzzer) -target_link_libraries(pkcs8 crypto) - -add_executable( - server - - server.cc -) - -target_link_libraries(server Fuzzer) -target_link_libraries(server crypto) -target_link_libraries(server ssl) - -add_executable( - client - - client.cc -) - -target_link_libraries(client Fuzzer) -target_link_libraries(client crypto) -target_link_libraries(client ssl) - -add_executable( - dtls_server - - dtls_server.cc -) - -target_link_libraries(dtls_server Fuzzer) -target_link_libraries(dtls_server crypto) -target_link_libraries(dtls_server ssl) - -add_executable( - dtls_client - - dtls_client.cc -) - -target_link_libraries(dtls_client Fuzzer) -target_link_libraries(dtls_client crypto) -target_link_libraries(dtls_client ssl) - -add_executable( - read_pem - - read_pem.cc -) - -target_link_libraries(read_pem Fuzzer) -target_link_libraries(read_pem crypto) - -add_executable( - ssl_ctx_api - - ssl_ctx_api.cc -) - -target_link_libraries(ssl_ctx_api Fuzzer) -target_link_libraries(ssl_ctx_api crypto) -target_link_libraries(ssl_ctx_api ssl) - -add_executable( - session - - session.cc - - $ -) - -target_link_libraries(session Fuzzer) -target_link_libraries(session crypto) -target_link_libraries(session ssl) +add_executable(session session.cc) +target_link_libraries(session Fuzzer crypto ssl) diff --git a/fuzz/pkcs12.cc b/fuzz/pkcs12.cc new file mode 100644 index 00000000..85bb0e34 --- /dev/null +++ b/fuzz/pkcs12.cc @@ -0,0 +1,29 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { + bssl::UniquePtr certs(sk_X509_new_null()); + EVP_PKEY *key = nullptr; + CBS cbs; + CBS_init(&cbs, buf, len); + PKCS12_get_key_and_certs(&key, certs.get(), &cbs, "foo"); + EVP_PKEY_free(key); + return 0; +} diff --git a/fuzz/pkcs12_corpus/04191202c1f7d978bcb3a4c1316d88b046689e31 b/fuzz/pkcs12_corpus/04191202c1f7d978bcb3a4c1316d88b046689e31 new file mode 100644 index 0000000000000000000000000000000000000000..5ead05fc12feccc137f3f04772dce390dce8a5c9 GIT binary patch literal 2567 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 Dg0#@W literal 0 HcmV?d00001 diff --git a/fuzz/pkcs12_corpus/aab806b45129f3284cf9598951cdd57a86e63ab5 b/fuzz/pkcs12_corpus/aab806b45129f3284cf9598951cdd57a86e63ab5 new file mode 100644 index 0000000000000000000000000000000000000000..1049426ea9bca68aeccf82e98caa0ba1c84b3d50 GIT binary patch literal 2469 zcmV;W30n3rf(fAl0Ru3C31;Jf0_HtY!4OG`FPw0vd<~J4?9Oxh82Mmpzl4 z=yIw}k9JWKSy=HJquX7)>Vz3pPXPPkS4Ya~zK?~A94C!|aDVYuSm7p=*e~9!$gID^ z#%HGVZ0sOByq($5p-zku87s4)-)fJd!_4-*33`@cAk+q#Om8EbOw4nOLP(iKkITqL z8v9WLYVsn5h@D}J7Blqso5&$gvCT02DTor>)G$oBtu)>N_`wpVO~)~rD@BL~G-+;a zG}zq=Jy~=%F>39RJ6niDMn7j}~AmHPkX|H)&5tn&LHzF<|Y0SK^&moPS2rR1PRpiyuZbBCK)8$`7=+di*q3rG|}W zT*o@w_<1^t_M#pM$q?z2I>qg>%DZOqoynX+b!0x|5-Vr;zblwswxGIsnBYfTcZE(S zasI1Zs4|o6&?b=N+AlPUP`EpLOkb%!im3Czw@?drPK==n z5A^u9n&W=Yx9$-XQi(e!nEaKet-oP3tr{dMNM>bqoLRt6Up-ok?$EIpZ8SzVpt^Ca zcXKJDH%|i7e-7x*|9}xiLIYZds{bVtA43^FsbZE4Z!?Hos`=uyx%XABwRTrWgX8)I z+J*v`v|z4T)oj5t;Wjpud7iDKExfg&>)p-ENJ163<_>mSS9B!iiNxp#ss6Jgrpj{S z+G#kZ!h5)&(D|>4a~BpirSMTJzazTjh;u?ZjA;~eMW=? zX*6L3P#=bpl<5l-TlN-#>-zD#1ZWq^HE+63Of$~(Cbx8}rO>Jkg%L1VV&6!|-^nLy^dm4$H_!}L^P%KlY5zJagVIw$EIFoFd^1_>&LNQU>aQsE5d8+{fwy{J(*>g9l*ZD+~ue-H( z>nk8Gz3MOCrZ3j4bfq-=-}eHdAQi}Aa=U*7_7C`e!{)0h=Gfs4T0Fp5uJ{`jJbQoj zpX~QPFi$;fMBNTdER$$MF{qbI_GWP^Qa(E7a*F2T$p2+%8b%?r@J4(LWzmkLkr7;z z>+7yY^t<@;ejqUT%^A&93V%=Ntf{PWmViYnN@I`#8PI+vQ!T_Gr5}lB57~853h~ta zF23fJJ8X>O4`0q$NZyU>)8Puu-!x6pTdP4qYwMve0ZMW%^j<`E$L1Ef`w%w(Eyg<+ zav|HShI{pJKXaqb4j{W(Oe4bRA|l`d4dkLfRh_`=n#A*}xbbuBN9ZkUp+J=O2f1$p zT6pDIK^n)+Ll7V+mEbCG^7sSbI&9vQnng_erKK_M;|UXO{TVku_U(@h z&P&nZJ^O_Kgc<9iV;w6kA?^rTZLqP{fdID936Qje7uhO29aF}^i`uRX3O*c)#MYNx zNauNgc&gqPU|lE`IzqRF$Y7HwuujSMM(6xapPv%n%We#>aoV@+Jx232K|Tos8^*9?>-)+nN6FJrd;_<@S>WrWJwfyF(st-fSoRQ=quQwEU zM&T(z3{Lfv9r!axZ=H+tC)B(4uKJ~mL65Z8FTp43a8(`R*bGWue21hCga^|&XDn3_ z{T|v)W&sim8+?3Rf+00!Tzb-G!Yf|5vCH3C$uYMVCYD}r9AZ6ir6-sXh$&f0r^B!k5dWo335wIV&ru=6g|fA5&B}^Z=x=pp&#S=dLKg zEjqKR*F1JaOS@`kn9leW6K8om6$!T@!0ZQ#{Y1-|z1-DPOqUx*ufS{u0h5YQQEKE| z3Q~bPb?u^;rd(BH?)x)>5U3#7!b8s;wFe3&D zDuzgg_YDCF6)_eB6cltVQjQG_25d59(|$8CXp1Nsbuck7AutIB1uG5%0vZJX1Qa5U j|5|wLEFq#uw_}J9M;yS@>{ literal 0 HcmV?d00001 diff --git a/fuzz/pkcs12_corpus/fff673b3287ad0d26ffa212d14d94ce2d015c7ab b/fuzz/pkcs12_corpus/fff673b3287ad0d26ffa212d14d94ce2d015c7ab new file mode 100644 index 0000000000000000000000000000000000000000..f7cd26f68d776196400fdb521a3edd3bc3fc674f GIT binary patch literal 2566 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 g^PM~tp`