openssl / project

Tracking of project related issues
1 stars 0 forks source link

Address clusterfuzz NULL pointer read in provider fuzzer #680

Open nhorman opened 1 week ago

nhorman commented 1 week ago

New error reported in clusterfuzz: https://oss-fuzz.com/testcase-detail/5110198501965824

given that pc points to NULL, I'm assuming that ctx->meth is null, but I'm not sure how it occured

### Tasks
- [ ] download the reproducer  corpora
- [ ] reproduce the issue locally
- [ ] inventigate and determine the root cause

Invest 1-3 days investigating the root cause of this issue open a new pr or issue to the address the failure

Sashan commented 1 day ago

This is essentialy same as #681 we are just arriving there with slightly different callstack. To reveal the stack one has to step through gdb to discover we die in EVP_DigestUpdate()

#0  EVP_DigestUpdate () at crypto/evp/digest.c:387
#1  0x0000555555b65070 in kmac_final () at providers/implementations/macs/kmac_prov.c:353
#2  0x0000555555a0e985 in evp_mac_final () at crypto/evp/mac_lib.c:165
#3  0x0000555555b35bed in kmac_derive () at providers/implementations/kdfs/kbkdf.c:269
#4  kbkdf_derive () at providers/implementations/kdfs/kbkdf.c:305
#5  0x00005555559471f0 in do_evp_kdf () at fuzz/provider.c:449
#6  0x000055555594470d in FuzzerTestOneInput () at fuzz/provider.c:619
#7  0x0000555555966c81 in ExecuteCallback () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614
#8  0x0000555555951415 in RunOneTest () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:327
#9  0x0000555555956eab in FuzzerDriver () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:862
#10 0x00005555559832a3 in main () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20

In EVP_DigestUpdate() we arrive to line 428 where we die instantly by jumping to NULL.

the kctx/vmacctx argument passed to kmac_final() function reads as follows:

(gdb) p *((struct kmac_data_st *)0x51a000000080)
$1 = {provctx = 0x50300000d060, ctx = 0x507000000790, digest = {md = 0x511000001940, alloc_md = 0x511000001940, 
    engine = 0x0}, out_len = 32, key_len = 0, custom_len = 0, xof_mode = 0, key = '\000' <repeats 671 times>, 
  custom = '\000' <repeats 515 times>}

We can just grab the ctx member and try to dereference it:

(gdb) p *((EVP_MD_CTX *)0x507000000790)
$2 = {reqdigest = 0x0, digest = 0x0, engine = 0x0, flags = 0, md_data = 0x0, pctx = 0x0, update = 0x0, algctx = 0x0, 
  fetched_digest = 0x0}

yup, this is zero-fill buffer. the EVP_DigestUpdate() gets called from here in kmac_final():

351
352     ok = right_encode(encoded_outlen, sizeof(encoded_outlen), &len, lbits)
353         && EVP_DigestUpdate(ctx, encoded_outlen, len)
354         && EVP_DigestFinalXOF(ctx, out, kctx->out_len);

according to gdb the len is 3 and ctx is buffer of zeros which is a lethal to EVP_DigestUpdate(). The fix from #681 will help too.