Skip to main content
← All libraries
Crypto · C

How to fuzz OpenSSL

Heartbleed proved that a single OOB read in OpenSSL breaks the entire internet.

OpenSSL's ASN.1 DER decoder, X.509 certificate parser, and TLS state machine are among the most security-critical C code on the internet. Its complexity — over 500 KLOC — means subtle length-field mismatches can survive years of code review, as Heartbleed demonstrated.

Common bug classes

  • Heap buffer over-read in ASN.1 DER length field (cf. Heartbleed)
  • Out-of-bounds write in BN bignum arithmetic on crafted parameters
  • Use-after-free in X.509 certificate chain verification
  • Integer overflow in EVP_EncryptUpdate buffer sizing
  • Null dereference in TLS session ticket extension parsing

Recommended setup

Fuzzers

  • AFL++
  • libFuzzer
  • Honggfuzz
  • Centipede

Sanitizers

  • ASan
  • UBSan
  • MSan

Harness scaffold

#include <stdint.h>
#include <stddef.h>
#include <openssl/x509.h>
#include <openssl/bio.h>

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  const uint8_t *p = data;
  X509 *cert = d2i_X509(NULL, &p, (long)size);
  if (cert) {
    X509_verify_cert_error_string(X509_V_ERR_UNSPECIFIED);
    X509_free(cert);
  }
  /* Also fuzz PEM path */
  BIO *bio = BIO_new_mem_buf(data, (int)size);
  if (bio) {
    X509 *pem_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
    if (pem_cert) X509_free(pem_cert);
    BIO_free(bio);
  }
  return 0;
}

Save this as fuzz_target.cc, build with your compiler + sanitizer flags, and you have a working starting point.

Notable CVEs found by fuzzing

  • CVE-2014-0160
  • CVE-2022-0778
  • CVE-2022-3602
Start fuzzing OpenSSL on Fuzze.rs →

Push the harness above + a Dockerfile. First month 50% off.