From 9386113166fdad850de51f1ada0dc40acf4eec43 Mon Sep 17 00:00:00 2001
From: Artur Cygan <artur.cygan@trailofbits.com>
Date: Mon, 12 Dec 2022 18:56:07 +0100
Subject: [PATCH] Fuzzing improvements

---
 fuzz/.gitignore                |    2 +
 fuzz/README.md                 |   19 +
 fuzz/openvpn-fuzz.py           |  158 +++++
 fuzz/shell.nix                 |   19 +
 fuzz/src/fuzz_base64.c         |   43 ++
 fuzz/src/fuzz_buffer.c         |  273 ++++++++
 fuzz/src/fuzz_dhcp.c           |   37 ++
 fuzz/src/fuzz_forward.c        |  227 +++++++
 fuzz/src/fuzz_list.c           |  137 ++++
 fuzz/src/fuzz_misc.c           |   79 +++
 fuzz/src/fuzz_mroute.c         |   70 +++
 fuzz/src/fuzz_mss.c            |   28 +
 fuzz/src/fuzz_packet_id.c      |  105 ++++
 fuzz/src/fuzz_parse_argv.c     |   47 ++
 fuzz/src/fuzz_proxy.c          |  137 ++++
 fuzz/src/fuzz_randomizer.cpp   |  114 ++++
 fuzz/src/fuzz_randomizer.h     |   28 +
 fuzz/src/fuzz_route.c          |  202 ++++++
 fuzz/src/fuzz_verify_cert.c    |  167 +++++
 fuzz/src/fuzz_verify_cert.h    | 1065 ++++++++++++++++++++++++++++++++
 src/openvpn/console_builtin.c  |   16 +
 src/openvpn/console_systemd.c  |    4 +
 src/openvpn/error.c            |    4 +
 src/openvpn/fake_fuzz_header.h |    2 +
 src/openvpn/fuzz.h             |   47 ++
 src/openvpn/fuzz_header.h      |   79 +++
 src/openvpn/misc.c             |   10 +
 src/openvpn/mroute.c           |    2 +
 src/openvpn/openvpn.c          |    4 +
 src/openvpn/packet_id.c        |    4 +
 src/openvpn/proxy.c            |   20 +
 src/openvpn/socket.c           |    4 +
 src/openvpn/socket.h           |    9 +
 33 files changed, 3162 insertions(+)
 create mode 100644 fuzz/.gitignore
 create mode 100644 fuzz/README.md
 create mode 100755 fuzz/openvpn-fuzz.py
 create mode 100644 fuzz/shell.nix
 create mode 100644 fuzz/src/fuzz_base64.c
 create mode 100644 fuzz/src/fuzz_buffer.c
 create mode 100644 fuzz/src/fuzz_dhcp.c
 create mode 100644 fuzz/src/fuzz_forward.c
 create mode 100644 fuzz/src/fuzz_list.c
 create mode 100644 fuzz/src/fuzz_misc.c
 create mode 100644 fuzz/src/fuzz_mroute.c
 create mode 100644 fuzz/src/fuzz_mss.c
 create mode 100644 fuzz/src/fuzz_packet_id.c
 create mode 100644 fuzz/src/fuzz_parse_argv.c
 create mode 100644 fuzz/src/fuzz_proxy.c
 create mode 100644 fuzz/src/fuzz_randomizer.cpp
 create mode 100644 fuzz/src/fuzz_randomizer.h
 create mode 100644 fuzz/src/fuzz_route.c
 create mode 100644 fuzz/src/fuzz_verify_cert.c
 create mode 100644 fuzz/src/fuzz_verify_cert.h
 create mode 100644 src/openvpn/fake_fuzz_header.h
 create mode 100644 src/openvpn/fuzz.h
 create mode 100644 src/openvpn/fuzz_header.h

diff --git a/fuzz/.gitignore b/fuzz/.gitignore
new file mode 100644
index 00000000000..641b59d91dc
--- /dev/null
+++ b/fuzz/.gitignore
@@ -0,0 +1,2 @@
+build
+corpus
diff --git a/fuzz/README.md b/fuzz/README.md
new file mode 100644
index 00000000000..247a3c0a929
--- /dev/null
+++ b/fuzz/README.md
@@ -0,0 +1,19 @@
+# OpenVPN Fuzzing
+
+## Setup
+The fuzzing setup is handled by Nix inside a `nix-shell` and works both on
+Linux and macOS. Nix is the only dependency (https://nixos.org/download.html).
+
+## Usage
+
+```sh
+$ nix-shell fuzz/shell.nix
+$ autoreconf -i -v -f
+$ ./configure --disable-lz4
+$ cd fuzz
+$ ./openvpn-fuzz.py fuzz base64
+$ ./openvpn-fuzz.py fuzz parse_argv -- -fork=4 -ignore_crashes=1
+$ ./openvpn-fuzz.py coverage base64 parse_argv # specified targets
+$ ./openvpn-fuzz.py coverage # all targets
+$ ./openvpn-fuzz.py coverage --clean # do make clean before and after, use if previously built for fuzzing
+```
diff --git a/fuzz/openvpn-fuzz.py b/fuzz/openvpn-fuzz.py
new file mode 100755
index 00000000000..d22062e363d
--- /dev/null
+++ b/fuzz/openvpn-fuzz.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+
+import argparse
+import os
+import platform
+import subprocess
+import sys
+
+TARGETS = [
+           'base64',
+           'buffer',
+           'dhcp',
+           'forward',
+           'list',
+           'misc',
+           'mroute',
+           'mss',
+           'packet_id',
+           'parse_argv',
+           'proxy',
+           'route',
+           'verify_cert',
+          ]
+
+BASE_DIR = os.path.dirname(os.path.realpath(__file__))
+
+def fuzz_target(target, args=[]):
+    build_targets([target])
+    os.makedirs(corpus_dir(target), exist_ok=True)
+    os.chdir(target_dir(target, "fuzzer"))
+    os.execv(target_bin_path(target, "fuzzer"),
+             [target_bin_path(target, "fuzzer"), corpus_dir(target)] + args)
+
+def generate_coverage_report(targets=TARGETS):
+    """
+    If OpenVPN was previously built for fuzzing run `make -C ../ clean` before and after generating coverage.
+    """
+    wd = os.getcwd()
+    build_targets(targets, for_coverage=True)
+    profraws = []
+    object_args = []
+    for target in targets:
+        os.chdir(target_dir(target, "coverage"))
+        profraws.append(target_dir(target, "coverage", "default.profraw"))
+        object_args.append("-object")
+        object_args.append(target_bin_path(target, "coverage"))
+        subprocess.run([target_bin_path(target, "coverage"), corpus_dir(target), "-runs=0"])
+
+    profdata = build_dir("coverage", "combined.profdata")
+    subprocess.run(["llvm-profdata", "merge", "-o", profdata, "-sparse"] + profraws)
+    subprocess.run(["llvm-cov", "show", "--format", "html", f"-instr-profile={profdata}",
+                    "-output-dir", build_dir("coverage", "report")] + object_args)
+    os.chdir(wd)
+
+def triage_parse_argv_crashes():
+    """
+    Filters out false positives that are caused by calling exit.
+    """
+    import pwn
+    target = "parse_argv"
+    for filename in os.listdir(target_dir(target, "fuzzer")):
+        if "crash-" in filename:
+            print("Triaging", filename)
+            with open(target_dir(target, "fuzzer", filename), "rb") as f:
+                argv_raw = f.read()
+                p = pwn.process(executable="../src/openvpn/openvpn", argv=argv_raw.split(b'\x00'))
+                out = p.readall()
+                if b"SIGSEGV" in out or b"smashing" or b"AddressSanitizer" in out:
+                    print(pwn.hexdump(argv_raw))
+                    print(out)
+                    exit(1)
+                p.close()
+
+def build_openvpn(cflags):
+    """
+    Build OpenVPN as usual, assumes `autoconf -f -v -f` and `./configure --disable-lz4` already run.
+    """
+    subprocess.run(["make", "-j", "-C", "../", f"CFLAGS={cflags}"])
+
+def build_targets(targets, for_coverage=False):
+    fuzzer_flags = '-g -fsanitize=address,fuzzer-no-link'
+    coverage_flags = '-g -fprofile-instr-generate -fcoverage-mapping'
+
+    build_subdir = 'coverage' if for_coverage else 'fuzzer'
+    os.makedirs(build_dir(build_subdir), exist_ok=True)
+
+    cflags = coverage_flags if for_coverage else fuzzer_flags
+    cflags += " -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
+    build_openvpn(cflags)
+
+    o_files = []
+    for file in os.listdir("../src/openvpn"):
+        if file.endswith(".o") and file != 'openvpn.o':
+            o_files.append("../src/openvpn/" + file)
+    subprocess.run(["ar", "r", build_dir(build_subdir, "libopenvpn.a")] + o_files)
+
+    subprocess.run(["clang++", "-c", "src/fuzz_randomizer.cpp",
+                    "-o", build_dir(build_subdir, "fuzz_randomizer.o")] +
+                   cflags.split(' '))
+
+    extra_libs = ["-lc++abi", "-lresolv"] if platform.system() == 'Darwin' else ['-lcap-ng']
+
+    for target in targets:
+        os.makedirs(target_dir(target, build_subdir), exist_ok=True)
+        subprocess.run(["clang", "-I../src/openvpn", "-I..", "-I../src/compat", "-I../include",
+                        "-lssl", "-lcrypto", "-llzo2", f"src/fuzz_{target}.c",
+                        build_dir(build_subdir, "libopenvpn.a"),
+                        build_dir(build_subdir, "fuzz_randomizer.o"),
+                        "-o", target_bin_path(target, build_subdir),
+                        "-g", "-fsanitize=address,fuzzer"] +
+                       (coverage_flags.split(' ') if for_coverage else []) +
+                       extra_libs)
+
+def build_dir(subdir, file=''):
+    """
+    There are two build flavors that live in their own subdirs: coverage and fuzzer.
+    """
+    return os.path.join(BASE_DIR, "build", subdir, file)
+
+def target_dir(target, subdir, file=''):
+    return os.path.join(build_dir(subdir), f"fuzz_{target}", file)
+
+def corpus_dir(target):
+    return os.path.join(BASE_DIR, "corpus", f"fuzz_{target}")
+
+def target_bin(target):
+    return f"fuzz_{target}"
+
+def target_bin_path(target, subdir):
+    return target_dir(target, subdir, target_bin(target))
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser()
+    subparsers = parser.add_subparsers(dest="subcommand")
+    fuzz_parser = subparsers.add_parser('fuzz')
+    fuzz_parser.add_argument('target', type=str)
+    fuzz_parser.add_argument('libfuzzer_args', type=str, nargs='*')
+    coverage_parser = subparsers.add_parser('coverage')
+    coverage_parser.add_argument('targets', type=str, nargs='*')
+    coverage_parser.add_argument('--clean', action=argparse.BooleanOptionalAction)
+
+    args = parser.parse_args()
+    if args.subcommand == 'fuzz':
+        # ./openvpn-fuzz.py fuzz proxy -- -fork=4 -ignore_crashes=1
+        fuzz_target(args.target, args.libfuzzer_args)
+    elif args.subcommand == 'coverage':
+        if args.clean:
+            subprocess.run(["make", "-C", "../", "clean"])
+
+        if args.targets:
+            generate_coverage_report(args.targets)
+        else:
+            generate_coverage_report()
+
+        if args.clean:
+            subprocess.run(["make", "-C", "../", "clean"])
+    else:
+        parser.print_help()
diff --git a/fuzz/shell.nix b/fuzz/shell.nix
new file mode 100644
index 00000000000..e689d3d7a57
--- /dev/null
+++ b/fuzz/shell.nix
@@ -0,0 +1,19 @@
+with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/e58a7747db96c23b8a977e7c1bbfc5753b81b6fa.tar.gz") {};
+
+let llvmPackages = llvmPackages_14;
+in llvmPackages.stdenv.mkDerivation {
+  name = "openvpn-fuzz";
+  buildInputs = [
+    autoconf
+    automake
+    m4
+    libtool
+    pkg-config
+    openssl_1_1
+    lz4
+    lzo
+    pam
+    llvmPackages.llvm
+    python3Packages.pwntools
+  ] ++ lib.optional (!stdenv.isDarwin) libcap_ng;
+}
diff --git a/fuzz/src/fuzz_base64.c b/fuzz/src/fuzz_base64.c
new file mode 100644
index 00000000000..c9c45b84b36
--- /dev/null
+++ b/fuzz/src/fuzz_base64.c
@@ -0,0 +1,43 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base64.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size > 500) {
+    return 0;
+  }
+
+  char *new_str = (char *)malloc(size + 1);
+  if (new_str == NULL) {
+    return 0;
+  }
+  memcpy(new_str, data, size);
+  new_str[size] = '\0';
+
+  char *str = NULL;
+  openvpn_base64_encode(data, size, &str);
+  if(str != NULL) {
+    free(str);
+  }
+
+  uint16_t outsize = 10000;
+  char *output_buf = (char *)malloc(outsize);
+  openvpn_base64_decode(new_str, output_buf, outsize);
+  free(output_buf);
+
+  free(new_str);
+  return 0;
+}
diff --git a/fuzz/src/fuzz_buffer.c b/fuzz/src/fuzz_buffer.c
new file mode 100644
index 00000000000..4062c41f35f
--- /dev/null
+++ b/fuzz/src/fuzz_buffer.c
@@ -0,0 +1,273 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#include "config.h"
+#include "syshead.h"
+#include "misc.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data,size);
+
+  struct gc_arena gc;
+  struct buffer *bufp;
+  struct buffer buf, buf2;
+  struct buffer_list *buflistp = NULL;
+  ssize_t generic_ssizet, _size;
+  char *tmp;
+  char *tmp2;
+  char match;
+
+  gc = gc_new();
+  bufp = NULL;
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+  for (int i = 0; i < total_to_fuzz; i++) {
+    if (bufp == NULL) {
+      generic_ssizet = fuzz_randomizer_get_byte(0, 1);
+      if (generic_ssizet == -1) goto cleanup;
+      if (generic_ssizet == 0) {
+        _size = fuzz_randomizer_get_byte(0, 100);
+        if (_size == -1) goto cleanup;
+        buf = alloc_buf_gc(_size, &gc);
+        bufp = &buf;
+      } else {
+        tmp = get_random_string();
+        buf = string_alloc_buf(tmp, &gc);
+        bufp = &buf;
+        free(tmp);
+        tmp = NULL;
+      }
+    } else {
+#define NUM_TARGETS 32
+      generic_ssizet = fuzz_randomizer_get_byte(0, NUM_TARGETS);
+      if (generic_ssizet == -1) goto cleanup;
+      switch (generic_ssizet) {
+      case 0:
+        buf_clear(bufp);
+        break;
+      case 1:
+        buf2 = clone_buf(bufp);
+        free_buf(&buf2);
+        break;
+      case 2:
+        buf_defined(bufp);
+        break;
+      case 3:
+        buf_valid(bufp);
+        break;
+      case 4:
+        buf_bptr(bufp);
+        break;
+      case 5:
+        buf_len(bufp);
+        break;
+      case 6:
+        buf_bend(bufp);
+        break;
+      case 7:
+        buf_blast(bufp);
+        break;
+      case 8:
+        buf_str(bufp);
+        break;
+      case 9:
+        generic_ssizet = fuzz_randomizer_get_byte(0, 255);
+        if (generic_ssizet == -1) goto cleanup;
+        buf_rmtail(bufp, (uint8_t)generic_ssizet);
+        break;
+      case 10:
+        buf_chomp(bufp);
+        break;
+      case 11:
+        tmp = get_random_string();
+        skip_leading_whitespace(tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 12:
+        tmp = get_random_string();
+        chomp(tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 13:
+        tmp = get_random_string();
+        tmp2 = get_random_string();
+        rm_trailing_chars(tmp, tmp2);
+        free(tmp);
+        free(tmp2);
+        tmp = NULL;
+        tmp2 = NULL;
+        break;
+      case 14:
+        tmp = get_random_string();
+        string_clear(tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 15:
+        tmp = get_random_string();
+        buf_string_match_head_str(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 16:
+        tmp = get_random_string();
+        buf_string_compare_advance(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 17:
+        generic_ssizet = fuzz_randomizer_get_byte(0, 255);
+        if (generic_ssizet == -1) goto cleanup;
+
+        tmp = get_random_string();
+        if (strlen(tmp) > 0) {
+          buf_parse(bufp, (int)generic_ssizet, tmp, strlen(tmp));
+        }
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 18:
+        tmp = get_random_string();
+        string_mod(tmp, fuzz_randomizer_get_int(0, 12312),
+                   fuzz_randomizer_get_int(0, 23141234),
+                   (char)fuzz_randomizer_get_int(0, 255));
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 19:
+        tmp = get_random_string();
+        match = (char)fuzz_randomizer_get_int(0, 255);
+        if (match != 0) {
+          string_replace_leading(tmp, match, (char)fuzz_randomizer_get_int(0, 255));
+        }
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 20:
+        tmp = get_random_string();
+        buf_write(bufp, tmp, strlen(tmp));
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 21:
+        tmp = get_random_string();
+
+        buf_write_prepend(bufp, tmp, strlen(tmp));
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 22:
+        buf_write_u8(bufp, fuzz_randomizer_get_int(0, 255));
+        break;
+      case 23:
+        buf_write_u16(bufp, fuzz_randomizer_get_int(0, 1024));
+        break;
+      case 24:
+        buf_write_u32(bufp, fuzz_randomizer_get_int(0, 12312));
+        break;
+      case 25:
+        tmp = get_random_string();
+        buf_catrunc(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 26:
+        convert_to_one_line(bufp);
+        break;
+      case 27:
+        buf_advance(bufp, fuzz_randomizer_get_int(0, 25523));
+        break;
+      case 28:
+        buf_prepend(bufp, fuzz_randomizer_get_int(0, 251235));
+        break;
+      case 29:
+        buf_reverse_capacity(bufp);
+        break;
+      case 30:
+        buf_forward_capacity_total(bufp);
+        break;
+      case 31:
+        buf_forward_capacity(bufp);
+        break;
+      case 32:
+        tmp = get_random_string();
+        buf_puts(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      }
+    }
+
+    if (buflistp == NULL) {
+      buflistp = buffer_list_new();
+    } else {
+#define NUM_LIST_TARGETS 6
+      generic_ssizet = fuzz_randomizer_get_byte(0, NUM_LIST_TARGETS);
+      if (generic_ssizet == -1) goto cleanup;
+      switch (generic_ssizet) {
+      case 0:
+        buffer_list_free(buflistp);
+        buflistp = NULL;
+        break;
+      case 1:
+        buffer_list_defined(buflistp);
+        break;
+      case 2:
+        tmp = get_random_string();
+        if (strlen(tmp) < BUF_SIZE_MAX) {
+          buffer_list_push(buflistp, tmp);
+        }
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 3:
+        buffer_list_peek(buflistp);
+        break;
+      case 4:
+        buffer_list_pop(buflistp);
+        break;
+      case 5:
+        tmp = get_random_string();
+        buffer_list_aggregate_separator(
+            buflistp, fuzz_randomizer_get_int(0, 1024), tmp);
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 6:
+        buffer_list_aggregate(buflistp,
+                              fuzz_randomizer_get_int(0, 1024));
+        break;
+      }
+    }
+  }
+
+cleanup:
+  // Cleanup
+  buffer_list_free(buflistp);
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_dhcp.c b/fuzz/src/fuzz_dhcp.c
new file mode 100644
index 00000000000..1368ac2a138
--- /dev/null
+++ b/fuzz/src/fuzz_dhcp.c
@@ -0,0 +1,37 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "dhcp.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  struct buffer ipbuf;
+  in_addr_t ret;
+
+  fuzz_random_init(data, size);
+  char *ran_val = get_random_string();
+
+  ipbuf = alloc_buf(strlen(ran_val));
+  if (buf_write(&ipbuf, ran_val, strlen(ran_val)) != false) {
+    ret = dhcp_extract_router_msg(&ipbuf);
+  }
+  free_buf(&ipbuf);
+
+  fuzz_random_destroy();
+  free(ran_val);
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_forward.c b/fuzz/src/fuzz_forward.c
new file mode 100644
index 00000000000..954f2d0608a
--- /dev/null
+++ b/fuzz/src/fuzz_forward.c
@@ -0,0 +1,227 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include <sys/time.h>
+#include "syshead.h"
+#include "interval.h"
+#include "init.h"
+#include "buffer.h"
+#include "forward.h"
+
+#include "fuzz_randomizer.h"
+
+static int init_c2_outgoing_link(struct context_2 *c2, struct gc_arena *gc) {
+  struct link_socket_actual *to_link_addr = NULL;
+  struct link_socket *link_socket = NULL;
+  struct socks_proxy_info *socks_proxy = NULL;
+  struct buffer buf;
+
+  c2->tun_write_bytes = 0;
+  ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc);
+  memset(link_socket, 0, sizeof(*link_socket));
+
+  c2->link_socket = link_socket;
+
+  if (fuzz_randomizer_get_int(0, 2) != 0) {
+    c2->link_socket->info.proto = PROTO_UDP;
+  } else {
+    c2->link_socket->info.proto = PROTO_TCP_SERVER;
+  }
+
+  ALLOC_ARRAY_GC(socks_proxy, struct socks_proxy_info, 1, gc);
+  memset(socks_proxy, 0, sizeof(*socks_proxy));
+  c2->link_socket->socks_proxy = socks_proxy;
+
+  //c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff);
+  //c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff);
+  c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff);
+  //c2->frame.link_mtu = fuzz_randomizer_get_int(0, 0xfffffff);
+
+  ALLOC_ARRAY_GC(to_link_addr, struct link_socket_actual, 1, gc);
+  memset(to_link_addr, 0, sizeof(*to_link_addr));
+  c2->to_link_addr = to_link_addr;
+
+  c2->to_link_addr->dest.addr.sa.sa_family = AF_INET;
+  c2->to_link_addr->dest.addr.in4.sin_addr.s_addr = 1;
+
+  char *tmp = get_random_string();
+  buf = alloc_buf_gc(strlen(tmp), gc);
+  buf_write(&buf, tmp, strlen(tmp));
+  int val = fuzz_randomizer_get_int(0, strlen(tmp));
+  buf.offset = val;
+  free(tmp);
+
+  c2->link_socket->stream_buf.maxlen = BLEN(&buf);
+  c2->to_link = buf;
+
+  if (buf.offset < 10) {
+    return -1;
+  }
+  return 0;
+}
+
+void fuzz_process_outgoing_link(const uint8_t *data, size_t size) {
+  struct context ctx;
+  struct gc_arena gc = gc_new();
+  memset(&ctx, 0, sizeof(ctx));
+
+  if (init_c2_outgoing_link(&ctx.c2, &gc) == 0) {
+    process_outgoing_link(&ctx);
+  }
+
+  gc_free(&gc);
+}
+
+static int _init_options(struct options *options, struct client_nat_entry **cne,
+                         struct gc_arena *gc) {
+  options->passtos = false;
+  options->mode = MODE_POINT_TO_POINT;
+  options->allow_recursive_routing = true;
+  options->client_nat = new_client_nat_list(gc);
+
+  struct client_nat_entry *_cne;
+  ALLOC_ARRAY_GC(cne[0], struct client_nat_entry, 1, gc);
+  _cne = cne[0];
+  memset(_cne, 0, sizeof(struct client_nat_entry));
+
+  struct client_nat_option_list clist;
+  clist.n = 1;
+  clist.entries[0] = *_cne;
+  copy_client_nat_option_list(options->client_nat, &clist);
+  options->route_gateway_via_dhcp = false;
+
+  return 0;
+}
+
+static int init_c2_incoming_tun(struct context_2 *c2, struct gc_arena *gc) {
+  struct buffer buf;
+  memset(&buf, 0, sizeof(buf));
+
+  struct link_socket *link_socket = NULL;
+  ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc);
+  c2->link_socket = link_socket;
+
+  ALLOC_OBJ_GC(c2->link_socket_info, struct link_socket_info, gc);
+  ALLOC_OBJ_GC(c2->link_socket_info->lsa, struct link_socket_addr, gc);
+  c2->link_socket_info->lsa->bind_local = NULL;
+  c2->link_socket_info->lsa->remote_list = NULL;
+  c2->link_socket_info->lsa->current_remote = NULL;
+  c2->link_socket_info->lsa->remote_list = NULL;
+  c2->es = env_set_create(gc);
+
+  //c2->frame.link_mtu_dynamic = 0;
+  //c2->frame.extra_frame = 0;
+  c2->frame.extra_tun = 0;
+  c2->to_link_addr = NULL;
+
+  char *tmp = get_random_string();
+  buf = alloc_buf(strlen(tmp));
+  buf_write(&buf, tmp, strlen(tmp));
+
+  int retval;
+  if (strlen(tmp) > 5) {
+    retval = 0;
+  } else {
+    retval = 1;
+  }
+
+  free(tmp);
+
+  c2->buf = buf;
+  c2->buffers = init_context_buffers(&c2->frame);
+  c2->log_rw = false;
+
+  return retval;
+}
+
+int run_process_incoming_tun(const uint8_t *data, size_t size) {
+  struct gc_arena gc;
+  struct context ctx;
+  struct client_nat_entry *cne[MAX_CLIENT_NAT];
+  struct route_list route_list;
+
+  memset(&ctx, 0, sizeof(ctx));
+  memset(cne, 0, sizeof(cne));
+
+  gc = gc_new();
+
+  _init_options(&ctx.options, cne, &gc);
+
+  // Init tuntap
+  struct tuntap tuntap;
+  tuntap.type = DEV_TYPE_TAP;
+
+  ctx.c1.tuntap = &tuntap;
+
+  int retval = init_c2_incoming_tun(&ctx.c2, &gc);
+  ctx.c1.route_list = &route_list;
+  if (retval == 0) {
+    process_incoming_tun(&ctx);
+  }
+
+  free(ctx.c2.buf.data);
+  free_context_buffers(ctx.c2.buffers);
+  gc_free(&gc);
+}
+
+static int init_c2_outgoing_tun(struct context_2 *c2, struct gc_arena *gc) {
+  struct buffer buf;
+
+  c2->tun_write_bytes = 0;
+  c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff);
+
+  char *tmp = get_random_string();
+  buf = alloc_buf_gc(strlen(tmp), gc);
+  buf_write(&buf, tmp, strlen(tmp));
+  free(tmp);
+
+  c2->to_tun = buf;
+  return 0;
+}
+
+void run_process_outgoing_tun(uint8_t *data, size_t size) {
+  struct gc_arena gc;
+  struct context ctx;
+  struct tuntap tuntap;
+
+  memset(&ctx, 0, sizeof(ctx));
+  gc = gc_new();
+
+  tuntap.type = DEV_TYPE_TAP;
+  ctx.c1.tuntap = &tuntap;
+
+  init_c2_outgoing_tun(&ctx.c2, &gc);
+  process_outgoing_tun(&ctx);
+
+  gc_free(&gc);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  int dec = fuzz_randomizer_get_byte(0, 2);
+  if (dec == -1) goto cleanup;
+  if (dec == 0) {
+    run_process_incoming_tun(data, size);
+  }
+	else if (dec == 1) {
+		run_process_outgoing_tun(data, size);
+	}
+  else {
+    fuzz_process_outgoing_link(data, size);
+  }
+
+cleanup:
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/fuzz/src/fuzz_list.c b/fuzz/src/fuzz_list.c
new file mode 100644
index 00000000000..d4bd579e547
--- /dev/null
+++ b/fuzz/src/fuzz_list.c
@@ -0,0 +1,137 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "list.h"
+
+#include "fuzz_randomizer.h"
+
+#define KEY_SIZE 23
+
+/* Required for hash_init() */
+static uint32_t word_hash_function(const void *key, uint32_t iv) {
+  return hash_func(key, KEY_SIZE, iv);
+}
+
+/* Required for hash_init() */
+static bool word_compare_function(const void *key1, const void *key2) {
+  return ((size_t)key1 & 0xFFF) == ((size_t)key1 & 0xFFF);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  struct gc_arena gc;
+  struct hash *hash = NULL;
+  ssize_t generic_ssizet, generic_ssizet2, num_loops;
+
+  fuzz_random_init(data, size);
+
+  gc = gc_new();
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+  for (int i = 0; i < total_to_fuzz; i++) {
+    generic_ssizet = fuzz_randomizer_get_byte(0, 8);
+    if (generic_ssizet == -1) goto cleanup;
+
+    switch (generic_ssizet) {
+    case 0:
+      if (hash == NULL) {
+        int n_buckets = fuzz_randomizer_get_int(1, 1000);
+        uint32_t iv;
+
+        hash =
+            hash_init(n_buckets, iv, word_hash_function, word_compare_function);
+      }
+      break;
+    case 1:
+      if (hash) {
+        hash_free(hash);
+        hash = NULL;
+      }
+      break;
+    case 2:
+      if (hash) {
+        struct hash_iterator hi;
+        struct hash_element *he;
+        hash_iterator_init(hash, &hi);
+        while ((he = hash_iterator_next(&hi))) {
+          void *w = he->value;
+        }
+        hash_iterator_free(&hi);
+      }
+      break;
+    case 3:
+      if (hash) {
+        void *key;
+        void *value;
+        char arr[KEY_SIZE];
+        memset(arr, 0, KEY_SIZE);
+        fuzz_get_random_data(arr, KEY_SIZE);
+        key = (void *)arr;
+        if (!hash_lookup(hash, key)) {
+          generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+          value = (void *)generic_ssizet;
+          hash_add(hash, key, value, false);
+        }
+      }
+      break;
+    case 4:
+      if (hash) {
+        hash_n_elements(hash);
+      }
+      break;
+    case 5:
+      if (hash) {
+        hash_n_buckets(hash);
+      }
+      break;
+    case 6:
+      if (hash) {
+        uint32_t hv;
+        generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+        hv = generic_ssizet;
+        hash_bucket(hash, hv);
+      }
+      break;
+    case 7:
+      if (hash) {
+        void *key;
+        char arr[KEY_SIZE];
+        memset(arr, 0, KEY_SIZE);
+        fuzz_get_random_data(arr, KEY_SIZE);
+        key = (void *)arr;
+        hash_remove(hash, key);
+      }
+      break;
+    case 8:
+      if (hash) {
+        void *value;
+        generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+        value = (void *)generic_ssizet;
+        hash_remove_by_value(hash, value);
+      }
+    default:
+      break;
+    }
+  }
+
+cleanup:
+  if (hash) {
+    hash_free(hash);
+  }
+
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_misc.c b/fuzz/src/fuzz_misc.c
new file mode 100644
index 00000000000..5485355d18a
--- /dev/null
+++ b/fuzz/src/fuzz_misc.c
@@ -0,0 +1,79 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#include "config.h"
+#include "syshead.h"
+#include "misc.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct gc_arena gc;
+  struct env_set *es;
+  gc = gc_new();
+  es = env_set_create(&gc);
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 9);
+  for (int i = 0; i <total_to_fuzz; i++) {
+    int type = fuzz_randomizer_get_byte(0, 8);
+    if (type == -1) goto cleanup;
+    char *tmp1 = get_random_string();
+    char *tmp2 = get_random_string();
+
+    switch (type) {
+    case 0:
+      env_set_del(es, tmp1);
+      break;
+    case 1:
+      env_set_add(es, tmp1);
+      break;
+    case 2:
+      env_set_get(es, tmp1);
+      break;
+    case 3:
+      if (strlen(tmp1) > 1 && strlen(tmp2) > 1) {
+        setenv_str(es, tmp2, tmp1);
+      }
+      break;
+    case 4:
+      hostname_randomize(tmp1, &gc);
+      break;
+    case 5:
+      if (strlen(tmp1) > 0) {
+        get_auth_challenge(tmp1, &gc);
+      }
+      break;
+    case 6:
+      output_peer_info_env(es, tmp1);
+      break;
+    case 7:
+      sanitize_control_message(tmp1, &gc);
+      break;
+    case 8:
+      prepend_dir(tmp1, tmp2, &gc);
+      break;
+    }
+    free(tmp1);
+    free(tmp2);
+  }
+
+cleanup:
+  env_set_destroy(es);
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/fuzz/src/fuzz_mroute.c b/fuzz/src/fuzz_mroute.c
new file mode 100644
index 00000000000..63d0ce23dd5
--- /dev/null
+++ b/fuzz/src/fuzz_mroute.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "init.h"
+#include "mroute.h"
+
+#include "fuzz_randomizer.h"
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+  fuzz_random_init(data, size);
+  struct buffer buf;
+  struct gc_arena gc;
+
+  gc = gc_new();
+
+  char *tmp = get_random_string();
+  buf = string_alloc_buf(tmp, &gc);
+  free(tmp);
+
+  struct mroute_addr src_addr;
+  struct mroute_addr dst_addr;
+  mroute_addr_init(&src_addr);
+  mroute_addr_init(&dst_addr);
+  unsigned int ret = mroute_extract_addr_ip(&src_addr, &dst_addr, &buf);
+
+  if (ret & MROUTE_EXTRACT_SUCCEEDED) {
+    mroute_addr_mask_host_bits(&src_addr);
+    mroute_addr_print(&src_addr, &gc);
+    mroute_learnable_address(&src_addr, &gc);
+  }
+
+  uint16_t vid;
+  struct mroute_addr a1, a2;
+  mroute_addr_init(&a1);
+  mroute_addr_init(&a2);
+  mroute_extract_addr_ether(&a1, &a2, vid, &buf);
+
+  if (size > sizeof(struct openvpn_sockaddr)) {
+    struct openvpn_sockaddr local_sock;
+    memcpy(&local_sock, data, sizeof(struct openvpn_sockaddr));
+    mroute_extract_openvpn_sockaddr(&a1, &local_sock, true);
+    mroute_extract_openvpn_sockaddr(&a1, &local_sock, false);
+  }
+
+  struct mroute_helper *mhelper = NULL;
+  mhelper = mroute_helper_init(fuzz_randomizer_get_int(0, 0xfffffff));
+  if (mhelper != NULL) {
+    mroute_helper_add_iroute46(mhelper, fuzz_randomizer_get_int(0, MR_HELPER_NET_LEN-1));
+    mroute_helper_free(mhelper);
+  }
+
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+  return 0;
+}
+
diff --git a/fuzz/src/fuzz_mss.c b/fuzz/src/fuzz_mss.c
new file mode 100644
index 00000000000..cf143823989
--- /dev/null
+++ b/fuzz/src/fuzz_mss.c
@@ -0,0 +1,28 @@
+#include "config.h"
+#include "syshead.h"
+
+#include "buffer.h"
+#include "mss.h"
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct buffer buf;
+
+  int src_len = fuzz_randomizer_get_int(0, 4096);
+  int maxmss = fuzz_randomizer_get_int(0, 4096);
+
+  buf = alloc_buf(size);
+  char* src = malloc(src_len);
+  fuzz_get_random_data(src, src_len);
+  if (buf_write(&buf, src, src_len) != false) {
+    mss_fixup_ipv4(&buf, maxmss);
+    mss_fixup_ipv6(&buf, maxmss);
+  }
+  free_buf(&buf);
+  free(src);
+
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/fuzz/src/fuzz_packet_id.c b/fuzz/src/fuzz_packet_id.c
new file mode 100644
index 00000000000..9ece9384e5f
--- /dev/null
+++ b/fuzz/src/fuzz_packet_id.c
@@ -0,0 +1,105 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "init.h"
+#include "packet_id.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct packet_id pid;
+  struct packet_id_net pin;
+  const int seq_backtrack = 10;
+  const int time_backtrack = 10;
+
+  packet_id_init(&pid, seq_backtrack, time_backtrack, "name", 0);
+
+  int total_sends = fuzz_randomizer_get_byte(0, 10);
+  if (total_sends == -1) goto cleanup;
+  for (int i = 0; i < total_sends; i++) {
+    update_time();
+    pin.time = fuzz_randomizer_get_int(0, 0xfffffff);
+    pin.id = fuzz_randomizer_get_int(0, 0xfffffff);
+
+    packet_id_reap_test(&pid.rec);
+    bool test = packet_id_test(&pid.rec, &pin);
+    if (test) {
+      packet_id_add(&pid.rec, &pin);
+    }
+  }
+  packet_id_free(&pid);
+
+  // packet id send
+  char *tmp2 = get_random_string();
+  if (strlen(tmp2) > sizeof(struct packet_id_send)) {
+    struct packet_id_send pidsend;
+    memcmp(&pidsend, tmp2, sizeof(struct packet_id_send));
+
+    struct timeval tv;
+    tv.tv_sec = pidsend.time;
+    tv.tv_usec = 0;
+    if (localtime(&tv)) {
+      struct buffer iv_buffer;
+      buf_set_write(&iv_buffer, tmp2, strlen(tmp2));
+      packet_id_write(&pidsend, &iv_buffer, false, false);
+      packet_id_write(&pidsend, &iv_buffer, false, true);
+      packet_id_write(&pidsend, &iv_buffer, true, true);
+      packet_id_write(&pidsend, &iv_buffer, true, false);
+    }
+  }
+  free(tmp2);
+
+  struct gc_arena gc;
+  gc = gc_new();
+  struct buffer buf;
+  char *tmp = get_random_string();
+  buf = string_alloc_buf(tmp, &gc);
+  free(tmp);
+  packet_id_read(&pid, &buf, false);
+  packet_id_read(&pid, &buf, true);
+  gc_free(&gc);
+
+	char filename[256];
+	sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+
+	FILE *fp = fopen(filename, "wb");
+	if (!fp) {
+    return 0;
+	}
+	fwrite(data, size, 1, fp);
+	fclose(fp);
+
+  struct packet_id_persist p;
+  memset(&p, 0, sizeof(struct packet_id_persist));
+  packet_id_persist_init(&p);
+  packet_id_persist_load(&p, filename);
+  struct timeval tv;
+  tv.tv_sec = p.time;
+  tv.tv_usec = 0;
+  if (localtime(&tv) != NULL) {
+    gc = gc_new();
+    p.id_last_written = fuzz_randomizer_get_int(0, 0xfffffff);
+    packet_id_persist_print(&p, &gc);
+    packet_id_persist_save(&p);
+    gc_free(&gc);
+  }
+
+cleanup:
+  packet_id_persist_close(&p);
+
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/fuzz/src/fuzz_parse_argv.c b/fuzz/src/fuzz_parse_argv.c
new file mode 100644
index 00000000000..3f4db8bf9c6
--- /dev/null
+++ b/fuzz/src/fuzz_parse_argv.c
@@ -0,0 +1,47 @@
+#include "config.h"
+#include "syshead.h"
+
+#include "buffer.h"
+#include "options.h"
+
+#define N 100
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < 10) { return 0; }
+  if (data[size-1] != 0) { return 0; }
+
+  struct gc_arena gc;
+  struct options options;
+  struct env_set *es;
+
+  gc = gc_new();
+  init_options(&options, false);
+  es = env_set_create(&gc);
+
+  char* argv[N+1];
+  memset(argv, 0, sizeof(argv));
+
+  int argv_pos = 0;
+
+  int last_start = 0;
+  for (int i = 0; i < size; i++) {
+    if (argv_pos >= N) goto cleanup;
+
+    if (data[i] == 0) {
+      if (last_start == i) goto cleanup; // don't want empty args
+      argv[argv_pos] = data+last_start;
+      last_start = i+1;
+      argv_pos++;
+    }
+  }
+
+  if (argv_pos > 1)
+    //parse_argv(&options, argv_pos, argv, M_USAGE, OPT_P_DEFAULT, NULL, es);
+    parse_argv(&options, argv_pos, argv, M_NOPREFIX | M_OPTERR, OPT_P_DEFAULT, NULL, es);
+
+cleanup:
+  env_set_destroy(es);
+  gc_free(&gc);
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_proxy.c b/fuzz/src/fuzz_proxy.c
new file mode 100644
index 00000000000..66a5918b585
--- /dev/null
+++ b/fuzz/src/fuzz_proxy.c
@@ -0,0 +1,137 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include <sys/time.h>
+#include "syshead.h"
+#include "interval.h"
+#include "proxy.h"
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+    OPENSSL_malloc_init();
+    SSL_library_init();
+    ERR_load_crypto_strings();
+
+    OpenSSL_add_all_algorithms();
+    OpenSSL_add_ssl_algorithms();
+    OpenSSL_add_all_digests();
+
+    SSL_load_error_strings();
+    return 1;
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+	char *tmp = NULL;
+  char *tmp2 = NULL;
+
+  fuzz_random_init(data, size);
+
+  struct gc_arena gc = gc_new();
+  struct http_proxy_info pi;
+  ssize_t generic_ssizet;
+  int signal_received = 0;
+  struct buffer lookahead = alloc_buf(1024);
+  struct event_timeout evt;
+
+  memset(&evt, 0, sizeof(struct event_timeout));
+  memset(&pi, 0, sizeof(struct http_proxy_info));
+  memset(&pi, 0, sizeof(pi));
+
+  generic_ssizet = 0;
+  char *fuzz_usrnm = fuzz_random_get_string_max_length(USER_PASS_LEN-1);
+  strcpy(pi.up.username, fuzz_usrnm);
+  if (strlen(pi.up.username) == 0) {
+    gc_free(&gc);
+    free_buf(&lookahead);
+    free(fuzz_usrnm);
+    fuzz_random_destroy();
+    return 0;
+  }
+
+  char *pswd = fuzz_random_get_string_max_length(USER_PASS_LEN-1);
+  strcpy(pi.up.password, pswd);
+  if (strlen(pi.up.password) == 0) {
+    gc_free(&gc);
+    free_buf(&lookahead);
+
+    free(pswd);
+    free(fuzz_usrnm);
+    fuzz_random_destroy();
+    return 0;
+  }
+
+  generic_ssizet = fuzz_randomizer_get_byte(0, 4);
+  if (generic_ssizet == -1) goto cleanup;
+  switch (generic_ssizet) {
+  case 0:
+    pi.auth_method = HTTP_AUTH_NONE;
+    break;
+  case 1:
+     pi.auth_method = HTTP_AUTH_BASIC;
+    break;
+  case 2:
+    pi.auth_method = HTTP_AUTH_DIGEST;
+    break;
+  case 3:
+    pi.auth_method = HTTP_AUTH_NTLM;
+    break;
+  case 4:
+    pi.auth_method = HTTP_AUTH_NTLM2;
+    break;
+  }
+
+  generic_ssizet = fuzz_randomizer_get_byte(0, 2);
+  if (generic_ssizet == -1) goto cleanup;
+  switch (generic_ssizet) {
+  case 0:
+    pi.options.auth_retry = PAR_NO;
+    break;
+  case 1:
+    pi.options.auth_retry = PAR_ALL;
+    break;
+  case 2:
+    pi.options.auth_retry = PAR_NCT;
+    break;
+  }
+
+  char *tmp_authenticate = get_random_string();
+  pi.proxy_authenticate = tmp_authenticate;
+
+  tmp = get_random_string();
+  pi.options.custom_headers[0].name = tmp;
+  tmp2 = get_random_string();
+  pi.options.custom_headers[0].content = tmp2;
+
+  establish_http_proxy_passthru(&pi, 0, "1.2.3.4", "777", &evt, &lookahead,
+                                &signal_received);
+
+cleanup:
+  free(pi.proxy_authenticate);
+  gc_free(&gc);
+  free_buf(&lookahead);
+
+  if (tmp != NULL)  free(tmp);
+  if (tmp2 != NULL) free(tmp2);
+
+  free(pswd);
+  free(fuzz_usrnm);
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_randomizer.cpp b/fuzz/src/fuzz_randomizer.cpp
new file mode 100644
index 00000000000..0ffbf886847
--- /dev/null
+++ b/fuzz/src/fuzz_randomizer.cpp
@@ -0,0 +1,114 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <assert.h>
+
+FuzzedDataProvider *prov = NULL;
+
+extern "C" void fuzz_random_init(const uint8_t *data, size_t size) {
+   assert(prov == NULL);
+   prov = new FuzzedDataProvider(data, size);
+}
+
+extern "C" void fuzz_random_destroy() {
+   assert(prov != NULL);
+  delete prov;
+  prov = NULL;
+}
+
+extern "C" char *get_random_string() {
+   assert(prov != NULL);
+
+   std::string s1 = prov->ConsumeRandomLengthString();
+   char *tmp = (char *)malloc(s1.size() + 1);
+   memcpy(tmp, s1.c_str(), s1.size());
+   tmp[s1.size()] = '\0';
+   return tmp;
+}
+
+extern "C" int fuzz_randomizer_get_int(int min, int max) {
+   assert(prov != NULL);
+   return prov->ConsumeIntegralInRange<int>(min, max);
+}
+
+extern "C" int fuzz_randomizer_get_byte(uint8_t min, uint8_t max) {
+   assert(prov != NULL);
+   if (prov->remaining_bytes() >= 1)
+     return prov->ConsumeIntegralInRange<uint8_t>(min, max);
+   else return -1;
+}
+
+extern "C" char *fuzz_random_get_string_max_length(int max_len) {
+  assert(prov != NULL);
+
+  std::string s1 = prov->ConsumeBytesAsString(
+                           prov->ConsumeIntegralInRange<uint32_t>(1, max_len));
+  char *tmp123 = (char*)malloc(s1.size()+1);
+  memcpy(tmp123, s1.c_str(), s1.size());
+  tmp123[s1.size()] = '\0';
+
+  return tmp123;
+}
+
+extern "C" size_t fuzz_get_random_data(void *buf, size_t len) {
+  assert(prov != NULL);
+  size_t ret_val;
+  char *cbuf = (char*)buf;
+
+  if (prov->remaining_bytes() == 0) {
+    return -1;
+  }
+
+  double prob = prov->ConsumeProbability<double>();
+  if (prob < 0.05) {
+    return 0;
+  }
+
+  //if (len == 1) {
+  //  ret_val = prov->ConsumeData(buf, 1);
+  //  return ret_val;
+  //}
+  ret_val = prov->ConsumeData(buf, len);
+  return ret_val;
+}
+
+
+// Simple garbage collector
+#define GB_SIZE 100
+void *pointer_arr[GB_SIZE];
+static int pointer_idx = 0;
+
+// If the garbage collector is used then this must be called as first thing
+// during a fuzz run.
+extern "C" void gb_init() {
+  pointer_idx = 0;
+
+   for (int i = 0; i < GB_SIZE; i++) {
+     pointer_arr[i] = NULL;
+   }
+}
+
+extern "C" void gb_cleanup() {
+  for(int i = 0; i < GB_SIZE; i++) {
+    if (pointer_arr[i] != NULL) {
+      free(pointer_arr[i]);
+    }
+  }
+}
+
+extern "C" char *gb_get_random_string() {
+  char *tmp = get_random_string();
+  pointer_arr[pointer_idx++] = (void*)tmp;
+  return tmp;
+}
+
diff --git a/fuzz/src/fuzz_randomizer.h b/fuzz/src/fuzz_randomizer.h
new file mode 100644
index 00000000000..da1f0098066
--- /dev/null
+++ b/fuzz/src/fuzz_randomizer.h
@@ -0,0 +1,28 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+
+void fuzz_random_init(const uint8_t *data, size_t size);
+void fuzz_random_destroy();
+char *get_random_string();
+int fuzz_randomizer_get_int(int min, int max);
+int fuzz_randomizer_get_byte(uint8_t min, uint8_t max);
+size_t fuzz_get_random_data(void *buf, size_t len);
+char *fuzz_random_get_string_max_length(int max_len);
+
+void gb_init();
+void gb_cleanup();
+char *gb_get_random_string();
+
+int fuzz_success;
diff --git a/fuzz/src/fuzz_route.c b/fuzz/src/fuzz_route.c
new file mode 100644
index 00000000000..73d7980b59b
--- /dev/null
+++ b/fuzz/src/fuzz_route.c
@@ -0,0 +1,202 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "init.h"
+#include "proxy.h"
+#include "interval.h"
+#include "route.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+  fuzz_random_init(data, size);
+
+  gb_init();
+
+  struct route_option_list *opt;
+  struct route_list rl;
+
+  int route_list_inited = 0;
+  int route_list_ipv6_inited = 0;
+
+  struct context c;
+  memset(&c, 0, sizeof(struct context));
+  gc_init(&c.gc);
+  c.es = env_set_create(&c.gc);
+  init_options(&c.options, true);
+  net_ctx_init(&c, &c.net_ctx);
+  init_verb_mute(&c, IVM_LEVEL_1);
+
+  init_options_dev(&c.options);
+
+  pre_setup(&c.options);
+
+  setenv_settings(c.es, &c.options);
+
+  ALLOC_OBJ_CLEAR_GC(c.options.connection_list, struct connection_list,
+                     &c.options.gc);
+  context_init_1(&c);
+
+  in_addr_t remote_host;
+  ssize_t default_metric;
+
+  struct route_ipv6_list rl6;
+  struct route_ipv6_option_list *opt6;
+
+  memset(&rl, 0, sizeof(rl));
+  memset(&rl6, 0, sizeof(rl6));
+  memset(&opt, 0, sizeof(opt));
+  memset(&opt6, 0, sizeof(opt6));
+
+  opt6 = new_route_ipv6_option_list(&c.gc);
+  opt = new_route_option_list(&c.gc);
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+  for (int i = 0; i < total_to_fuzz; i++) {
+    int selector = fuzz_randomizer_get_byte(0, 13);
+    if (selector == -1) goto cleanup;
+    switch (selector) {
+    case 0:
+      if (route_list_inited == 0) {
+        const char *remote_endpoint = gb_get_random_string();
+        memset(&rl, 0, sizeof(struct route_list));
+        rl.flags = fuzz_randomizer_get_int(0, 0xffffff);
+
+        init_route_list(&rl, opt, remote_endpoint, default_metric, remote_host,
+                        c.es, &c);
+        route_list_inited = 1;
+      }
+      break;
+    case 1:
+      if (route_list_inited) {
+        in_addr_t addr;
+        route_list_add_vpn_gateway(&rl, c.es, addr);
+      }
+      break;
+    case 2:
+      if (route_list_inited && route_list_ipv6_inited) {
+        struct tuntap tt;
+        memset(&tt, 0, sizeof(tt));
+        add_routes(&rl, &rl6, &tt, 0, c.es, &c);
+      }
+      break;
+    case 3:
+      if (route_list_inited) {
+        setenv_routes(c.es, &rl);
+      }
+      break;
+    case 4:
+      if (route_list_inited) {
+        struct route_ipv4 r;
+        struct route_option ro;
+        ro.network = gb_get_random_string();
+        ro.netmask = gb_get_random_string();
+        ro.gateway = gb_get_random_string();
+        ro.metric = gb_get_random_string();
+        ro.next = NULL;
+
+        memset(&r, 0, sizeof(struct route_ipv4));
+        r.option = &ro;
+        r.flags = RT_DEFINED;
+        add_route(&r, NULL, 0, NULL, c.es, &c);
+      }
+      break;
+    case 5:
+      if (route_list_inited) {
+        char *s1 = get_random_string();
+        is_special_addr(s1);
+        free(s1);
+      }
+      break;
+    case 6:
+      if (route_list_ipv6_inited == 0) {
+        const char *remote_endpoint = gb_get_random_string();
+        memset(&rl, 0, sizeof(struct route_list));
+        struct in6_addr remote_host;
+
+        rl6.rgi6.flags = fuzz_randomizer_get_int(0, 0xffffff);
+        fuzz_get_random_data(&rl6.rgi6.hwaddr, 6);
+
+        char *t1 = gb_get_random_string();
+        if (strlen(t1) > 16) {
+          memcpy(rl6.rgi6.iface, t1, 16);
+        } else {
+          memcpy(rl6.rgi6.iface, t1, strlen(t1));
+        }
+
+        init_route_ipv6_list(&rl6, opt6, remote_endpoint, 0, &remote_host, c.es,
+                             &c);
+        route_list_ipv6_inited = 1;
+      }
+      break;
+    case 7: {
+      unsigned int flags;
+      struct route_ipv6 r6;
+      struct tuntap tt;
+      memset(&tt, 0, sizeof(tt));
+      tt.actual_name = gb_get_random_string();
+      r6.iface = gb_get_random_string();
+      r6.flags = fuzz_randomizer_get_int(0, 0xfffff);
+      r6.netbits = fuzz_randomizer_get_int(0, 0xfffff);
+      r6.metric = fuzz_randomizer_get_int(0, 0xfffff);
+
+      r6.next = NULL;
+
+      add_route_ipv6(&r6, &tt, 0, c.es, &c);
+    } break;
+    case 8:
+      if (route_list_ipv6_inited && route_list_inited) {
+        delete_routes(&rl, &rl6, NULL, 0, c.es, &c);
+        route_list_ipv6_inited = 0;
+        route_list_inited = 0;
+      }
+      break;
+    case 9:
+      if (route_list_ipv6_inited) {
+        setenv_routes_ipv6(c.es, &rl6);
+      }
+      break;
+    case 10: {
+      add_route_ipv6_to_option_list(opt6, gb_get_random_string(),
+                                    gb_get_random_string(),
+                                    gb_get_random_string());
+    } break;
+    case 11: {
+      print_route_options(opt, M_NONFATAL);
+    } break;
+    case 12: {
+      add_route_to_option_list(opt, gb_get_random_string(),
+                               gb_get_random_string(), gb_get_random_string(),
+                               gb_get_random_string());
+    } break;
+    default:
+      break;
+    }
+  }
+
+cleanup:
+  if (route_list_inited) {
+    gc_free(&rl.gc);
+  }
+  env_set_destroy(c.es);
+  context_gc_free(&c);
+
+  fuzz_random_destroy();
+
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_verify_cert.c b/fuzz/src/fuzz_verify_cert.c
new file mode 100644
index 00000000000..c73a6ac828c
--- /dev/null
+++ b/fuzz/src/fuzz_verify_cert.c
@@ -0,0 +1,167 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "fuzz_verify_cert.h"
+#include "misc.h"
+#include "manage.h"
+#include "otime.h"
+#include "base64.h"
+#include "ssl_verify.h"
+#include "ssl_verify_backend.h"
+
+#include "fuzz_randomizer.h"
+
+
+static int parse_x509(const uint8_t *data, size_t size, X509 **out) {
+  *out = d2i_X509(NULL, (const unsigned char **)&data, size);
+  if (*out == NULL) {
+    return -1;
+  }
+
+  return 0;
+}
+
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  OPENSSL_malloc_init();
+  SSL_library_init();
+  ERR_load_crypto_strings();
+
+  OpenSSL_add_all_algorithms();
+  OpenSSL_add_ssl_algorithms();
+
+  SSL_load_error_strings();
+  return 1;
+}
+
+
+static int init_session_opt(struct tls_options **_opt, struct gc_arena *gc) {
+  ssize_t nid;
+  ssize_t generic_ssizet;
+  struct tls_options *opt;
+  int r;
+
+  ALLOC_OBJ_GC(*_opt, struct tls_options, gc);
+  if (opt == NULL) {
+		return -1;
+  }
+
+  opt = *_opt;
+
+  memset(opt, 0xFE, sizeof(struct tls_options));
+
+  opt->es = env_set_create(gc);
+  opt->x509_username_field[0] = NULL;
+  opt->remote_cert_eku = NULL;
+
+  /* Prevents failure if x509 sha1 hashes do not match */
+  opt->verify_hash = NULL;
+
+  /* Prevent attempt to run --tls-verify script */
+  opt->verify_command = NULL;
+
+  /* Do not verify against CRL file */
+  opt->crl_file = NULL;
+
+  /* Do not run --tls-verify plugins */
+  opt->plugins = NULL;
+
+  r = fuzz_randomizer_get_int(0, 1);
+  if (r == 0) {
+    opt->x509_username_field[0] = nidstrs[fuzz_randomizer_get_int(0, (sizeof(nidstrs)/sizeof(nidstrs[0])) - 1)];
+  } 
+  else {
+    opt->x509_username_field[0] = "ext:subjectAltName";
+  }
+  opt->x509_username_field[1] = NULL;
+
+  r = fuzz_randomizer_get_int(0, 2);
+  if (r == 0)
+    opt->ns_cert_type = NS_CERT_CHECK_CLIENT;
+  else if (r == 1)
+    opt->ns_cert_type = NS_CERT_CHECK_SERVER;
+  else
+    opt->ns_cert_type = NS_CERT_CHECK_NONE;
+
+  opt->x509_track = NULL;
+
+  r = fuzz_randomizer_get_int(0, 1);
+  if (r == 0)
+    opt->remote_cert_eku = NULL;
+  else
+    opt->remote_cert_eku = get_random_string();
+
+  return 0;
+}
+
+
+static int init_session(struct tls_session **_session, struct gc_arena *gc) {
+  struct tls_session *session;
+
+  ALLOC_OBJ_GC(*_session, struct tls_session, gc);
+  if (*_session == NULL) {
+		return -1;
+  }
+
+  session = *_session;
+  memset(session, 0xFE, sizeof(struct tls_session));
+
+  /* Accessed in set_common_name() */
+  session->common_name = get_random_string();;
+
+  /* Initialize the session->opt structure */
+  if (init_session_opt(&(session->opt), gc) == -1) {
+    free(session->common_name);
+		return -1;
+  }
+
+  /* Accessed in server_untrusted() */
+  session->untrusted_addr.dest.addr.sa.sa_family = AF_UNSPEC;
+
+  return 0;
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct gc_arena gc;
+  struct tls_session *session = NULL;
+  X509 *x509 = NULL;
+  gc = gc_new();
+
+  if (parse_x509(data, size, &x509) == 0) {
+    if (init_session(&session, &gc) == 0) {
+      verify_cert(session, x509, 100);
+      if (session->opt->remote_cert_eku != NULL) {
+        free(session->opt->remote_cert_eku);
+      }
+      free(session->common_name);
+    }
+    
+  }
+
+  X509_free(x509);
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/fuzz/src/fuzz_verify_cert.h b/fuzz/src/fuzz_verify_cert.h
new file mode 100644
index 00000000000..8a53669b32b
--- /dev/null
+++ b/fuzz/src/fuzz_verify_cert.h
@@ -0,0 +1,1065 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+static char* nidstrs[] = {
+"AD_DVCS",
+"AES-128-CBC",
+"AES-128-CBC-HMAC-SHA1",
+"AES-128-CBC-HMAC-SHA256",
+"AES-128-CFB",
+"AES-128-CFB1",
+"AES-128-CFB8",
+"AES-128-CTR",
+"AES-128-ECB",
+"AES-128-OCB",
+"AES-128-OFB",
+"AES-128-XTS",
+"AES-192-CBC",
+"AES-192-CBC-HMAC-SHA1",
+"AES-192-CBC-HMAC-SHA256",
+"AES-192-CFB",
+"AES-192-CFB1",
+"AES-192-CFB8",
+"AES-192-CTR",
+"AES-192-ECB",
+"AES-192-OCB",
+"AES-192-OFB",
+"AES-256-CBC",
+"AES-256-CBC-HMAC-SHA1",
+"AES-256-CBC-HMAC-SHA256",
+"AES-256-CFB",
+"AES-256-CFB1",
+"AES-256-CFB8",
+"AES-256-CTR",
+"AES-256-ECB",
+"AES-256-OCB",
+"AES-256-OFB",
+"AES-256-XTS",
+"AuthDSS",
+"AuthECDSA",
+"AuthGOST01",
+"AuthGOST12",
+"AuthNULL",
+"AuthPSK",
+"AuthRSA",
+"AuthSRP",
+"BF-CBC",
+"BF-CFB",
+"BF-ECB",
+"BF-OFB",
+"BLAKE2b512",
+"BLAKE2s256",
+"C",
+"CAMELLIA-128-CBC",
+"CAMELLIA-128-CCM",
+"CAMELLIA-128-CFB",
+"CAMELLIA-128-CFB1",
+"CAMELLIA-128-CFB8",
+"CAMELLIA-128-CMAC",
+"CAMELLIA-128-CTR",
+"CAMELLIA-128-ECB",
+"CAMELLIA-128-GCM",
+"CAMELLIA-128-OFB",
+"CAMELLIA-192-CBC",
+"CAMELLIA-192-CCM",
+"CAMELLIA-192-CFB",
+"CAMELLIA-192-CFB1",
+"CAMELLIA-192-CFB8",
+"CAMELLIA-192-CMAC",
+"CAMELLIA-192-CTR",
+"CAMELLIA-192-ECB",
+"CAMELLIA-192-GCM",
+"CAMELLIA-192-OFB",
+"CAMELLIA-256-CBC",
+"CAMELLIA-256-CCM",
+"CAMELLIA-256-CFB",
+"CAMELLIA-256-CFB1",
+"CAMELLIA-256-CFB8",
+"CAMELLIA-256-CMAC",
+"CAMELLIA-256-CTR",
+"CAMELLIA-256-ECB",
+"CAMELLIA-256-GCM",
+"CAMELLIA-256-OFB",
+"CAST5-CBC",
+"CAST5-CFB",
+"CAST5-ECB",
+"CAST5-OFB",
+"CMAC",
+"CN",
+"CRLReason",
+"CSPName",
+"ChaCha20",
+"ChaCha20-Poly1305",
+"CrlID",
+"DC",
+"DES-CBC",
+"DES-CDMF",
+"DES-CFB",
+"DES-CFB1",
+"DES-CFB8",
+"DES-ECB",
+"DES-EDE",
+"DES-EDE-CBC",
+"DES-EDE-CFB",
+"DES-EDE-OFB",
+"DES-EDE3",
+"DES-EDE3-CBC",
+"DES-EDE3-CFB",
+"DES-EDE3-CFB1",
+"DES-EDE3-CFB8",
+"DES-EDE3-OFB",
+"DES-OFB",
+"DESX-CBC",
+"DOD",
+"DSA",
+"DSA-SHA",
+"DSA-SHA1",
+"DSA-SHA1-old",
+"DSA-old",
+"DVCS",
+"GN",
+"HKDF",
+"HMAC",
+"HMAC-MD5",
+"HMAC-SHA1",
+"IANA",
+"IDEA-CBC",
+"IDEA-CFB",
+"IDEA-ECB",
+"IDEA-OFB",
+"INN",
+"ISO",
+"ISO-US",
+"ITU-T",
+"JOINT-ISO-ITU-T",
+"KISA",
+"KxDHE",
+"KxDHE-PSK",
+"KxECDHE",
+"KxECDHE-PSK",
+"KxGOST",
+"KxPSK",
+"KxRSA",
+"KxRSA_PSK",
+"KxSRP",
+"L",
+"LocalKeySet",
+"MD2",
+"MD4",
+"MD5",
+"MD5-SHA1",
+"MDC2",
+"MGF1",
+"Mail",
+"NULL",
+"Netscape",
+"Nonce",
+"O",
+"OCSP",
+"OCSPSigning",
+"OGRN",
+"ORG",
+"OU",
+"Oakley-EC2N-3",
+"Oakley-EC2N-4",
+"PBE-MD2-DES",
+"PBE-MD2-RC2-64",
+"PBE-MD5-DES",
+"PBE-MD5-RC2-64",
+"PBE-SHA1-2DES",
+"PBE-SHA1-3DES",
+"PBE-SHA1-DES",
+"PBE-SHA1-RC2-128",
+"PBE-SHA1-RC2-40",
+"PBE-SHA1-RC2-64",
+"PBE-SHA1-RC4-128",
+"PBE-SHA1-RC4-40",
+"PBES2",
+"PBKDF2",
+"PBMAC1",
+"PKIX",
+"PSPECIFIED",
+"RC2-40-CBC",
+"RC2-64-CBC",
+"RC2-CBC",
+"RC2-CFB",
+"RC2-ECB",
+"RC2-OFB",
+"RC4",
+"RC4-40",
+"RC4-HMAC-MD5",
+"RC5-CBC",
+"RC5-CFB",
+"RC5-ECB",
+"RC5-OFB",
+"RIPEMD160",
+"RSA",
+"RSA-MD2",
+"RSA-MD4",
+"RSA-MD5",
+"RSA-MDC2",
+"RSA-NP-MD5",
+"RSA-RIPEMD160",
+"RSA-SHA",
+"RSA-SHA1",
+"RSA-SHA1-2",
+"RSA-SHA224",
+"RSA-SHA256",
+"RSA-SHA384",
+"RSA-SHA512",
+"RSAES-OAEP",
+"RSASSA-PSS",
+"SEED-CBC",
+"SEED-CFB",
+"SEED-ECB",
+"SEED-OFB",
+"SHA",
+"SHA1",
+"SHA224",
+"SHA256",
+"SHA384",
+"SHA512",
+"SMIME",
+"SMIME-CAPS",
+"SN",
+"SNILS",
+"ST",
+"SXNetID",
+"TLS1-PRF",
+"UID",
+"UNDEF",
+"X25519",
+"X448",
+"X500",
+"X500algorithms",
+"X509",
+"X9-57",
+"X9cm",
+"ZLIB",
+"aRecord",
+"aaControls",
+"ac-auditEntity",
+"ac-proxying",
+"ac-targeting",
+"acceptableResponses",
+"account",
+"ad_timestamping",
+"algorithm",
+"ansi-X9-62",
+"anyExtendedKeyUsage",
+"anyPolicy",
+"archiveCutoff",
+"associatedDomain",
+"associatedName",
+"audio",
+"authorityInfoAccess",
+"authorityKeyIdentifier",
+"authorityRevocationList",
+"basicConstraints",
+"basicOCSPResponse",
+"biometricInfo",
+"brainpoolP160r1",
+"brainpoolP160t1",
+"brainpoolP192r1",
+"brainpoolP192t1",
+"brainpoolP224r1",
+"brainpoolP224t1",
+"brainpoolP256r1",
+"brainpoolP256t1",
+"brainpoolP320r1",
+"brainpoolP320t1",
+"brainpoolP384r1",
+"brainpoolP384t1",
+"brainpoolP512r1",
+"brainpoolP512t1",
+"buildingName",
+"businessCategory",
+"c2onb191v4",
+"c2onb191v5",
+"c2onb239v4",
+"c2onb239v5",
+"c2pnb163v1",
+"c2pnb163v2",
+"c2pnb163v3",
+"c2pnb176v1",
+"c2pnb208w1",
+"c2pnb272w1",
+"c2pnb304w1",
+"c2pnb368w1",
+"c2tnb191v1",
+"c2tnb191v2",
+"c2tnb191v3",
+"c2tnb239v1",
+"c2tnb239v2",
+"c2tnb239v3",
+"c2tnb359v1",
+"c2tnb431r1",
+"cACertificate",
+"cNAMERecord",
+"caIssuers",
+"caRepository",
+"capwapAC",
+"capwapWTP",
+"caseIgnoreIA5StringSyntax",
+"certBag",
+"certicom-arc",
+"certificateIssuer",
+"certificatePolicies",
+"certificateRevocationList",
+"challengePassword",
+"characteristic-two-field",
+"clearance",
+"clientAuth",
+"codeSigning",
+"contentType",
+"countersignature",
+"crlBag",
+"crlDistributionPoints",
+"crlNumber",
+"crossCertificatePair",
+"cryptocom",
+"cryptopro",
+"ct_cert_scts",
+"ct_precert_poison",
+"ct_precert_scts",
+"ct_precert_signer",
+"dITRedirect",
+"dNSDomain",
+"dSAQuality",
+"data",
+"dcobject",
+"deltaCRL",
+"deltaRevocationList",
+"description",
+"destinationIndicator",
+"dh-cofactor-kdf",
+"dh-std-kdf",
+"dhKeyAgreement",
+"dhSinglePass-cofactorDH-sha1kdf-scheme",
+"dhSinglePass-cofactorDH-sha224kdf-scheme",
+"dhSinglePass-cofactorDH-sha256kdf-scheme",
+"dhSinglePass-cofactorDH-sha384kdf-scheme",
+"dhSinglePass-cofactorDH-sha512kdf-scheme",
+"dhSinglePass-stdDH-sha1kdf-scheme",
+"dhSinglePass-stdDH-sha224kdf-scheme",
+"dhSinglePass-stdDH-sha256kdf-scheme",
+"dhSinglePass-stdDH-sha384kdf-scheme",
+"dhSinglePass-stdDH-sha512kdf-scheme",
+"dhpublicnumber",
+"directory",
+"distinguishedName",
+"dmdName",
+"dnQualifier",
+"document",
+"documentAuthor",
+"documentIdentifier",
+"documentLocation",
+"documentPublisher",
+"documentSeries",
+"documentTitle",
+"documentVersion",
+"domain",
+"domainRelatedObject",
+"dsa_with_SHA224",
+"dsa_with_SHA256",
+"ecdsa-with-Recommended",
+"ecdsa-with-SHA1",
+"ecdsa-with-SHA224",
+"ecdsa-with-SHA256",
+"ecdsa-with-SHA384",
+"ecdsa-with-SHA512",
+"ecdsa-with-Specified",
+"emailAddress",
+"emailProtection",
+"enhancedSearchGuide",
+"enterprises",
+"experimental",
+"extReq",
+"extendedCertificateAttributes",
+"extendedKeyUsage",
+"extendedStatus",
+"facsimileTelephoneNumber",
+"favouriteDrink",
+"freshestCRL",
+"friendlyCountry",
+"friendlyCountryName",
+"friendlyName",
+"generationQualifier",
+"gost-mac",
+"gost-mac-12",
+"gost2001",
+"gost2001cc",
+"gost2012_256",
+"gost2012_512",
+"gost89",
+"gost89-cbc",
+"gost89-cnt",
+"gost89-cnt-12",
+"gost89-ctr",
+"gost89-ecb",
+"gost94",
+"gost94cc",
+"grasshopper-cbc",
+"grasshopper-cfb",
+"grasshopper-ctr",
+"grasshopper-ecb",
+"grasshopper-mac",
+"grasshopper-ofb",
+"hmacWithMD5",
+"hmacWithSHA1",
+"hmacWithSHA224",
+"hmacWithSHA256",
+"hmacWithSHA384",
+"hmacWithSHA512",
+"holdInstructionCallIssuer",
+"holdInstructionCode",
+"holdInstructionNone",
+"holdInstructionReject",
+"homePostalAddress",
+"homeTelephoneNumber",
+"host",
+"houseIdentifier",
+"iA5StringSyntax",
+"id-DHBasedMac",
+"id-Gost28147-89-CryptoPro-A-ParamSet",
+"id-Gost28147-89-CryptoPro-B-ParamSet",
+"id-Gost28147-89-CryptoPro-C-ParamSet",
+"id-Gost28147-89-CryptoPro-D-ParamSet",
+"id-Gost28147-89-CryptoPro-KeyMeshing",
+"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+"id-Gost28147-89-None-KeyMeshing",
+"id-Gost28147-89-TestParamSet",
+"id-Gost28147-89-cc",
+"id-GostR3410-2001-CryptoPro-A-ParamSet",
+"id-GostR3410-2001-CryptoPro-B-ParamSet",
+"id-GostR3410-2001-CryptoPro-C-ParamSet",
+"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+"id-GostR3410-2001-ParamSet-cc",
+"id-GostR3410-2001-TestParamSet",
+"id-GostR3410-2001DH",
+"id-GostR3410-94-CryptoPro-A-ParamSet",
+"id-GostR3410-94-CryptoPro-B-ParamSet",
+"id-GostR3410-94-CryptoPro-C-ParamSet",
+"id-GostR3410-94-CryptoPro-D-ParamSet",
+"id-GostR3410-94-CryptoPro-XchA-ParamSet",
+"id-GostR3410-94-CryptoPro-XchB-ParamSet",
+"id-GostR3410-94-CryptoPro-XchC-ParamSet",
+"id-GostR3410-94-TestParamSet",
+"id-GostR3410-94-a",
+"id-GostR3410-94-aBis",
+"id-GostR3410-94-b",
+"id-GostR3410-94-bBis",
+"id-GostR3410-94DH",
+"id-GostR3411-94-CryptoProParamSet",
+"id-GostR3411-94-TestParamSet",
+"id-GostR3411-94-with-GostR3410-2001",
+"id-GostR3411-94-with-GostR3410-2001-cc",
+"id-GostR3411-94-with-GostR3410-94",
+"id-GostR3411-94-with-GostR3410-94-cc",
+"id-HMACGostR3411-94",
+"id-PasswordBasedMAC",
+"id-aca",
+"id-aca-accessIdentity",
+"id-aca-authenticationInfo",
+"id-aca-chargingIdentity",
+"id-aca-encAttrs",
+"id-aca-group",
+"id-aca-role",
+"id-ad",
+"id-aes128-CCM",
+"id-aes128-GCM",
+"id-aes128-wrap",
+"id-aes128-wrap-pad",
+"id-aes192-CCM",
+"id-aes192-GCM",
+"id-aes192-wrap",
+"id-aes192-wrap-pad",
+"id-aes256-CCM",
+"id-aes256-GCM",
+"id-aes256-wrap",
+"id-aes256-wrap-pad",
+"id-alg",
+"id-alg-PWRI-KEK",
+"id-alg-des40",
+"id-alg-dh-pop",
+"id-alg-dh-sig-hmac-sha1",
+"id-alg-noSignature",
+"id-camellia128-wrap",
+"id-camellia192-wrap",
+"id-camellia256-wrap",
+"id-cct",
+"id-cct-PKIData",
+"id-cct-PKIResponse",
+"id-cct-crs",
+"id-ce",
+"id-characteristic-two-basis",
+"id-cmc",
+"id-cmc-addExtensions",
+"id-cmc-confirmCertAcceptance",
+"id-cmc-dataReturn",
+"id-cmc-decryptedPOP",
+"id-cmc-encryptedPOP",
+"id-cmc-getCRL",
+"id-cmc-getCert",
+"id-cmc-identification",
+"id-cmc-identityProof",
+"id-cmc-lraPOPWitness",
+"id-cmc-popLinkRandom",
+"id-cmc-popLinkWitness",
+"id-cmc-queryPending",
+"id-cmc-recipientNonce",
+"id-cmc-regInfo",
+"id-cmc-responseInfo",
+"id-cmc-revokeRequest",
+"id-cmc-senderNonce",
+"id-cmc-statusInfo",
+"id-cmc-transactionId",
+"id-ct-asciiTextWithCRLF",
+"id-ct-xml",
+"id-ecPublicKey",
+"id-hex-multipart-message",
+"id-hex-partial-message",
+"id-it",
+"id-it-caKeyUpdateInfo",
+"id-it-caProtEncCert",
+"id-it-confirmWaitTime",
+"id-it-currentCRL",
+"id-it-encKeyPairTypes",
+"id-it-implicitConfirm",
+"id-it-keyPairParamRep",
+"id-it-keyPairParamReq",
+"id-it-origPKIMessage",
+"id-it-preferredSymmAlg",
+"id-it-revPassphrase",
+"id-it-signKeyPairTypes",
+"id-it-subscriptionRequest",
+"id-it-subscriptionResponse",
+"id-it-suppLangTags",
+"id-it-unsupportedOIDs",
+"id-kp",
+"id-mod-attribute-cert",
+"id-mod-cmc",
+"id-mod-cmp",
+"id-mod-cmp2000",
+"id-mod-crmf",
+"id-mod-dvcs",
+"id-mod-kea-profile-88",
+"id-mod-kea-profile-93",
+"id-mod-ocsp",
+"id-mod-qualified-cert-88",
+"id-mod-qualified-cert-93",
+"id-mod-timestamp-protocol",
+"id-on",
+"id-on-permanentIdentifier",
+"id-on-personalData",
+"id-pda",
+"id-pda-countryOfCitizenship",
+"id-pda-countryOfResidence",
+"id-pda-dateOfBirth",
+"id-pda-gender",
+"id-pda-placeOfBirth",
+"id-pe",
+"id-pkinit",
+"id-pkip",
+"id-pkix-mod",
+"id-pkix1-explicit-88",
+"id-pkix1-explicit-93",
+"id-pkix1-implicit-88",
+"id-pkix1-implicit-93",
+"id-ppl",
+"id-ppl-anyLanguage",
+"id-ppl-independent",
+"id-ppl-inheritAll",
+"id-qcs",
+"id-qcs-pkixQCSyntax-v1",
+"id-qt",
+"id-qt-cps",
+"id-qt-unotice",
+"id-regCtrl",
+"id-regCtrl-authenticator",
+"id-regCtrl-oldCertID",
+"id-regCtrl-pkiArchiveOptions",
+"id-regCtrl-pkiPublicationInfo",
+"id-regCtrl-protocolEncrKey",
+"id-regCtrl-regToken",
+"id-regInfo",
+"id-regInfo-certReq",
+"id-regInfo-utf8Pairs",
+"id-scrypt",
+"id-set",
+"id-smime-aa",
+"id-smime-aa-contentHint",
+"id-smime-aa-contentIdentifier",
+"id-smime-aa-contentReference",
+"id-smime-aa-dvcs-dvc",
+"id-smime-aa-encapContentType",
+"id-smime-aa-encrypKeyPref",
+"id-smime-aa-equivalentLabels",
+"id-smime-aa-ets-CertificateRefs",
+"id-smime-aa-ets-RevocationRefs",
+"id-smime-aa-ets-archiveTimeStamp",
+"id-smime-aa-ets-certCRLTimestamp",
+"id-smime-aa-ets-certValues",
+"id-smime-aa-ets-commitmentType",
+"id-smime-aa-ets-contentTimestamp",
+"id-smime-aa-ets-escTimeStamp",
+"id-smime-aa-ets-otherSigCert",
+"id-smime-aa-ets-revocationValues",
+"id-smime-aa-ets-sigPolicyId",
+"id-smime-aa-ets-signerAttr",
+"id-smime-aa-ets-signerLocation",
+"id-smime-aa-macValue",
+"id-smime-aa-mlExpandHistory",
+"id-smime-aa-msgSigDigest",
+"id-smime-aa-receiptRequest",
+"id-smime-aa-securityLabel",
+"id-smime-aa-signatureType",
+"id-smime-aa-signingCertificate",
+"id-smime-aa-smimeEncryptCerts",
+"id-smime-aa-timeStampToken",
+"id-smime-alg",
+"id-smime-alg-3DESwrap",
+"id-smime-alg-CMS3DESwrap",
+"id-smime-alg-CMSRC2wrap",
+"id-smime-alg-ESDH",
+"id-smime-alg-ESDHwith3DES",
+"id-smime-alg-ESDHwithRC2",
+"id-smime-alg-RC2wrap",
+"id-smime-cd",
+"id-smime-cd-ldap",
+"id-smime-ct",
+"id-smime-ct-DVCSRequestData",
+"id-smime-ct-DVCSResponseData",
+"id-smime-ct-TDTInfo",
+"id-smime-ct-TSTInfo",
+"id-smime-ct-authData",
+"id-smime-ct-authEnvelopedData",
+"id-smime-ct-compressedData",
+"id-smime-ct-contentCollection",
+"id-smime-ct-contentInfo",
+"id-smime-ct-publishCert",
+"id-smime-ct-receipt",
+"id-smime-cti",
+"id-smime-cti-ets-proofOfApproval",
+"id-smime-cti-ets-proofOfCreation",
+"id-smime-cti-ets-proofOfDelivery",
+"id-smime-cti-ets-proofOfOrigin",
+"id-smime-cti-ets-proofOfReceipt",
+"id-smime-cti-ets-proofOfSender",
+"id-smime-mod",
+"id-smime-mod-cms",
+"id-smime-mod-ess",
+"id-smime-mod-ets-eSigPolicy-88",
+"id-smime-mod-ets-eSigPolicy-97",
+"id-smime-mod-ets-eSignature-88",
+"id-smime-mod-ets-eSignature-97",
+"id-smime-mod-msg-v3",
+"id-smime-mod-oid",
+"id-smime-spq",
+"id-smime-spq-ets-sqt-unotice",
+"id-smime-spq-ets-sqt-uri",
+"id-tc26",
+"id-tc26-agreement",
+"id-tc26-agreement-gost-3410-2012-256",
+"id-tc26-agreement-gost-3410-2012-512",
+"id-tc26-algorithms",
+"id-tc26-cipher",
+"id-tc26-cipher-constants",
+"id-tc26-constants",
+"id-tc26-digest",
+"id-tc26-digest-constants",
+"id-tc26-gost-28147-constants",
+"id-tc26-gost-28147-param-Z",
+"id-tc26-gost-3410-2012-512-constants",
+"id-tc26-gost-3410-2012-512-paramSetA",
+"id-tc26-gost-3410-2012-512-paramSetB",
+"id-tc26-gost-3410-2012-512-paramSetTest",
+"id-tc26-hmac-gost-3411-2012-256",
+"id-tc26-hmac-gost-3411-2012-512",
+"id-tc26-mac",
+"id-tc26-sign",
+"id-tc26-sign-constants",
+"id-tc26-signwithdigest",
+"id-tc26-signwithdigest-gost3410-2012-256",
+"id-tc26-signwithdigest-gost3410-2012-512",
+"identified-organization",
+"info",
+"inhibitAnyPolicy",
+"initials",
+"international-organizations",
+"internationaliSDNNumber",
+"invalidityDate",
+"ipsecEndSystem",
+"ipsecIKE",
+"ipsecTunnel",
+"ipsecUser",
+"issuerAltName",
+"issuerSignTool",
+"issuingDistributionPoint",
+"janetMailbox",
+"jurisdictionC",
+"jurisdictionL",
+"jurisdictionST",
+"keyBag",
+"keyUsage",
+"lastModifiedBy",
+"lastModifiedTime",
+"localKeyID",
+"mXRecord",
+"mail",
+"mailPreferenceOption",
+"manager",
+"md_gost12_256",
+"md_gost12_512",
+"md_gost94",
+"member",
+"member-body",
+"messageDigest",
+"mgmt",
+"mime-mhs",
+"mime-mhs-bodies",
+"mime-mhs-headings",
+"mobileTelephoneNumber",
+"msCTLSign",
+"msCodeCom",
+"msCodeInd",
+"msEFS",
+"msExtReq",
+"msSGC",
+"msSmartcardLogin",
+"msUPN",
+"nSRecord",
+"name",
+"nameConstraints",
+"noCheck",
+"noRevAvail",
+"nsBaseUrl",
+"nsCaPolicyUrl",
+"nsCaRevocationUrl",
+"nsCertExt",
+"nsCertSequence",
+"nsCertType",
+"nsComment",
+"nsDataType",
+"nsRenewalUrl",
+"nsRevocationUrl",
+"nsSGC",
+"nsSslServerName",
+"onBasis",
+"organizationalStatus",
+"otherMailbox",
+"owner",
+"pagerTelephoneNumber",
+"path",
+"pbeWithMD5AndCast5CBC",
+"personalSignature",
+"personalTitle",
+"photo",
+"physicalDeliveryOfficeName",
+"pilot",
+"pilotAttributeSyntax",
+"pilotAttributeType",
+"pilotAttributeType27",
+"pilotDSA",
+"pilotGroups",
+"pilotObject",
+"pilotObjectClass",
+"pilotOrganization",
+"pilotPerson",
+"pkInitClientAuth",
+"pkInitKDC",
+"pkcs",
+"pkcs1",
+"pkcs3",
+"pkcs5",
+"pkcs7",
+"pkcs7-data",
+"pkcs7-digestData",
+"pkcs7-encryptedData",
+"pkcs7-envelopedData",
+"pkcs7-signedAndEnvelopedData",
+"pkcs7-signedData",
+"pkcs8ShroudedKeyBag",
+"pkcs9",
+"policyConstraints",
+"policyMappings",
+"postOfficeBox",
+"postalAddress",
+"postalCode",
+"ppBasis",
+"preferredDeliveryMethod",
+"presentationAddress",
+"prf-gostr3411-94",
+"prime-field",
+"prime192v1",
+"prime192v2",
+"prime192v3",
+"prime239v1",
+"prime239v2",
+"prime239v3",
+"prime256v1",
+"private",
+"privateKeyUsagePeriod",
+"protocolInformation",
+"proxyCertInfo",
+"pseudonym",
+"pss",
+"qcStatements",
+"qualityLabelledData",
+"rFC822localPart",
+"registeredAddress",
+"role",
+"roleOccupant",
+"room",
+"roomNumber",
+"rsaEncryption",
+"rsaOAEPEncryptionSET",
+"rsaSignature",
+"rsadsi",
+"sOARecord",
+"safeContentsBag",
+"sbgp-autonomousSysNum",
+"sbgp-ipAddrBlock",
+"sbgp-routerIdentifier",
+"sdsiCertificate",
+"searchGuide",
+"secp112r1",
+"secp112r2",
+"secp128r1",
+"secp128r2",
+"secp160k1",
+"secp160r1",
+"secp160r2",
+"secp192k1",
+"secp224k1",
+"secp224r1",
+"secp256k1",
+"secp384r1",
+"secp521r1",
+"secretBag",
+"secretary",
+"sect113r1",
+"sect113r2",
+"sect131r1",
+"sect131r2",
+"sect163k1",
+"sect163r1",
+"sect163r2",
+"sect193r1",
+"sect193r2",
+"sect233k1",
+"sect233r1",
+"sect239k1",
+"sect283k1",
+"sect283r1",
+"sect409k1",
+"sect409r1",
+"sect571k1",
+"sect571r1",
+"secureShellClient",
+"secureShellServer",
+"security",
+"seeAlso",
+"selected-attribute-types",
+"sendOwner",
+"sendProxiedOwner",
+"sendProxiedRouter",
+"sendRouter",
+"serialNumber",
+"serverAuth",
+"serviceLocator",
+"set-addPolicy",
+"set-attr",
+"set-brand",
+"set-brand-AmericanExpress",
+"set-brand-Diners",
+"set-brand-IATA-ATA",
+"set-brand-JCB",
+"set-brand-MasterCard",
+"set-brand-Novus",
+"set-brand-Visa",
+"set-certExt",
+"set-ctype",
+"set-msgExt",
+"set-policy",
+"set-policy-root",
+"set-rootKeyThumb",
+"setAttr-Cert",
+"setAttr-GenCryptgrm",
+"setAttr-IssCap",
+"setAttr-IssCap-CVM",
+"setAttr-IssCap-Sig",
+"setAttr-IssCap-T2",
+"setAttr-PGWYcap",
+"setAttr-SecDevSig",
+"setAttr-T2Enc",
+"setAttr-T2cleartxt",
+"setAttr-TokICCsig",
+"setAttr-Token-B0Prime",
+"setAttr-Token-EMV",
+"setAttr-TokenType",
+"setCext-IssuerCapabilities",
+"setCext-PGWYcapabilities",
+"setCext-TokenIdentifier",
+"setCext-TokenType",
+"setCext-Track2Data",
+"setCext-cCertRequired",
+"setCext-certType",
+"setCext-hashedRoot",
+"setCext-merchData",
+"setCext-setExt",
+"setCext-setQualf",
+"setCext-tunneling",
+"setct-AcqCardCodeMsg",
+"setct-AcqCardCodeMsgTBE",
+"setct-AuthReqTBE",
+"setct-AuthReqTBS",
+"setct-AuthResBaggage",
+"setct-AuthResTBE",
+"setct-AuthResTBEX",
+"setct-AuthResTBS",
+"setct-AuthResTBSX",
+"setct-AuthRevReqBaggage",
+"setct-AuthRevReqTBE",
+"setct-AuthRevReqTBS",
+"setct-AuthRevResBaggage",
+"setct-AuthRevResData",
+"setct-AuthRevResTBE",
+"setct-AuthRevResTBEB",
+"setct-AuthRevResTBS",
+"setct-AuthTokenTBE",
+"setct-AuthTokenTBS",
+"setct-BCIDistributionTBS",
+"setct-BatchAdminReqData",
+"setct-BatchAdminReqTBE",
+"setct-BatchAdminResData",
+"setct-BatchAdminResTBE",
+"setct-CRLNotificationResTBS",
+"setct-CRLNotificationTBS",
+"setct-CapReqTBE",
+"setct-CapReqTBEX",
+"setct-CapReqTBS",
+"setct-CapReqTBSX",
+"setct-CapResData",
+"setct-CapResTBE",
+"setct-CapRevReqTBE",
+"setct-CapRevReqTBEX",
+"setct-CapRevReqTBS",
+"setct-CapRevReqTBSX",
+"setct-CapRevResData",
+"setct-CapRevResTBE",
+"setct-CapTokenData",
+"setct-CapTokenSeq",
+"setct-CapTokenTBE",
+"setct-CapTokenTBEX",
+"setct-CapTokenTBS",
+"setct-CardCInitResTBS",
+"setct-CertInqReqTBS",
+"setct-CertReqData",
+"setct-CertReqTBE",
+"setct-CertReqTBEX",
+"setct-CertReqTBS",
+"setct-CertResData",
+"setct-CertResTBE",
+"setct-CredReqTBE",
+"setct-CredReqTBEX",
+"setct-CredReqTBS",
+"setct-CredReqTBSX",
+"setct-CredResData",
+"setct-CredResTBE",
+"setct-CredRevReqTBE",
+"setct-CredRevReqTBEX",
+"setct-CredRevReqTBS",
+"setct-CredRevReqTBSX",
+"setct-CredRevResData",
+"setct-CredRevResTBE",
+"setct-ErrorTBS",
+"setct-HODInput",
+"setct-MeAqCInitResTBS",
+"setct-OIData",
+"setct-PANData",
+"setct-PANOnly",
+"setct-PANToken",
+"setct-PCertReqData",
+"setct-PCertResTBS",
+"setct-PI",
+"setct-PI-TBS",
+"setct-PIData",
+"setct-PIDataUnsigned",
+"setct-PIDualSignedTBE",
+"setct-PIUnsignedTBE",
+"setct-PInitResData",
+"setct-PResData",
+"setct-RegFormReqTBE",
+"setct-RegFormResTBS",
+"setext-cv",
+"setext-genCrypt",
+"setext-miAuth",
+"setext-pinAny",
+"setext-pinSecure",
+"setext-track2",
+"signingTime",
+"simpleSecurityObject",
+"singleLevelQuality",
+"snmpv2",
+"street",
+"subjectAltName",
+"subjectDirectoryAttributes",
+"subjectInfoAccess",
+"subjectKeyIdentifier",
+"subjectSignTool",
+"subtreeMaximumQuality",
+"subtreeMinimumQuality",
+"supportedAlgorithms",
+"supportedApplicationContext",
+"targetInformation",
+"telephoneNumber",
+"teletexTerminalIdentifier",
+"telexNumber",
+"textEncodedORAddress",
+"textNotice",
+"timeStamping",
+"title",
+"tlsfeature",
+"tpBasis",
+"trustRoot",
+"ucl",
+"uid",
+"uniqueMember",
+"unstructuredAddress",
+"unstructuredName",
+"userCertificate",
+"userClass",
+"userPassword",
+"valid",
+"wap",
+"wap-wsg",
+"wap-wsg-idm-ecid-wtls1",
+"wap-wsg-idm-ecid-wtls10",
+"wap-wsg-idm-ecid-wtls11",
+"wap-wsg-idm-ecid-wtls12",
+"wap-wsg-idm-ecid-wtls3",
+"wap-wsg-idm-ecid-wtls4",
+"wap-wsg-idm-ecid-wtls5",
+"wap-wsg-idm-ecid-wtls6",
+"wap-wsg-idm-ecid-wtls7",
+"wap-wsg-idm-ecid-wtls8",
+"wap-wsg-idm-ecid-wtls9",
+"whirlpool",
+"x121Address",
+"x500UniqueIdentifier",
+"x509Certificate",
+"x509Crl",
+};
diff --git a/src/openvpn/console_builtin.c b/src/openvpn/console_builtin.c
index 3b97aad9eb2..719989a9fd1 100644
--- a/src/openvpn/console_builtin.c
+++ b/src/openvpn/console_builtin.c
@@ -157,7 +157,11 @@ static FILE *
 open_tty(const bool write)
 {
     FILE *ret;
+    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    ret = fuzz_fopen("/dev/tty", write ? "w" : "r");
+    #else
     ret = fopen("/dev/tty", write ? "w" : "r");
+    #endif
     if (!ret)
     {
         ret = write ? stderr : stdin;
@@ -176,7 +180,11 @@ close_tty(FILE *fp)
 {
     if (fp != stderr && fp != stdin)
     {
+        #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        fuzz_fclose(fp);
+        #else
         fclose(fp);
+        #endif
     }
 }
 
@@ -212,7 +220,11 @@ get_console_input(const char *prompt, const bool echo, char *input, const int ca
      * (in which case neither stdin or stderr are connected to a tty and
      * /dev/tty can not be open()ed anymore)
      */
+    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    if (!fuzz_isatty(0) && !fuzz_isatty(2) )
+    #else
     if (!isatty(0) && !isatty(2) )
+    #endif
     {
         int fd = open( "/dev/tty", O_RDWR );
         if (fd < 0)
@@ -239,7 +251,11 @@ get_console_input(const char *prompt, const bool echo, char *input, const int ca
         restore_tty = (tcsetattr(fileno(fp), TCSAFLUSH, &tty_tmp) == 0);
     }
 
+    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    if (fuzz_fgets(input, capacity, fp) != NULL)
+    #else
     if (fgets(input, capacity, fp) != NULL)
+    #endif
     {
         chomp(input);
         ret = true;
diff --git a/src/openvpn/console_systemd.c b/src/openvpn/console_systemd.c
index c7cf1adad38..b59dbea41de 100644
--- a/src/openvpn/console_systemd.c
+++ b/src/openvpn/console_systemd.c
@@ -78,7 +78,11 @@ get_console_input_systemd(const char *prompt, const bool echo, char *input, cons
         return false;
     }
     memset(input, 0, capacity);
+    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    if (fuzz_read(std_out, input, capacity-1) != 0)
+    #else
     if (read(std_out, input, capacity-1) != 0)
+    #endif
     {
         chomp(input);
         ret = true;
diff --git a/src/openvpn/error.c b/src/openvpn/error.c
index c8c77358ea7..779b2387c93 100644
--- a/src/openvpn/error.c
+++ b/src/openvpn/error.c
@@ -198,7 +198,11 @@ msg_fp(const unsigned int flags)
     FILE *fp = msgfp;
     if (!fp)
     {
+        #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        fp = stdout;
+        #else
         fp = (flags & (M_FATAL|M_USAGE_SMALL)) ? default_err : default_out;
+        #endif
     }
     if (!fp)
     {
diff --git a/src/openvpn/fake_fuzz_header.h b/src/openvpn/fake_fuzz_header.h
new file mode 100644
index 00000000000..dcaceba0f23
--- /dev/null
+++ b/src/openvpn/fake_fuzz_header.h
@@ -0,0 +1,2 @@
+ssize_t fuzz_get_random_data(void *buf, size_t len) { return 0; }
+int fuzz_success;
diff --git a/src/openvpn/fuzz.h b/src/openvpn/fuzz.h
new file mode 100644
index 00000000000..10e33c3ee28
--- /dev/null
+++ b/src/openvpn/fuzz.h
@@ -0,0 +1,47 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+// Returns a NULL-terminated C string that should be freed by the caller.
+char *get_modifiable_string(FuzzedDataProvider &provider) {
+  std::string s1 = provider.ConsumeRandomLengthString();
+  char *tmp = (char *)malloc(s1.size() + 1);
+  memcpy(tmp, s1.c_str(), s1.size());
+  tmp[s1.size()] = '\0';
+  return tmp;
+}
+
+FuzzedDataProvider *prov = NULL;
+
+
+extern "C" ssize_t fuzz_get_random_data(void *buf, size_t len) {
+  size_t ret_val;
+  char *cbuf = (char*)buf;
+
+  if (prov->remaining_bytes() == 0) {
+    return -1;
+  }
+
+  double prob = prov->ConsumeProbability<double>();
+  if (prob < 0.05) {
+    return 0;
+  }
+
+  if (len == 1) {
+    ret_val = prov->ConsumeData(buf, 1);
+    return ret_val;
+  }
+  ret_val = prov->ConsumeData(buf, len);
+  return ret_val;
+}
+
diff --git a/src/openvpn/fuzz_header.h b/src/openvpn/fuzz_header.h
new file mode 100644
index 00000000000..e86b70c62b8
--- /dev/null
+++ b/src/openvpn/fuzz_header.h
@@ -0,0 +1,79 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef FUZZ_H
+#define FUZZ_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+// Forward declared because we want to use FuzzedDataProvider,
+// which requires CPP.
+extern ssize_t fuzz_get_random_data(void *buf, size_t len);
+
+ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags){
+	return fuzz_get_random_data(buf, len);
+}
+
+ssize_t fuzz_read(int sockfd, void *buf, size_t len){
+	return fuzz_get_random_data(buf, len);
+}
+
+ssize_t fuzz_write(int fd, const void *buf, size_t count) {
+  return count;
+}
+
+int fuzz_isatty(int fd) {
+  return 1;
+}
+
+char *fuzz_fgets(char *s, int size, FILE *stream) {
+  ssize_t v = fuzz_get_random_data(s, size-1);
+  // We use fgets to get trusted input. As such, assume we have
+  // an ascii printable char at the beginning.
+  printf("Calling into fgets\n");
+  if (s[0] <= 0x21 || s[0] >= 0x7f) {
+    s[0] = 'A';
+  }
+  s[size-1] = '\0';
+  return s;
+}
+
+int fuzz_select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout) {
+  char val;
+  ssize_t c = fuzz_get_random_data(&val, 1);
+  return c;
+}
+
+ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags) {
+  return len;
+}
+
+FILE *fp_p = NULL;
+FILE *fuzz_fopen(const char *pathname, const char *mode) {
+   if (mode == NULL) return fp_p;
+   return fp_p;
+}
+
+int fuzz_fclose(FILE *stream) {
+   if (stream == NULL) return 1;
+   return 2;
+}
+
+size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen) {
+  if (buf == NULL) {
+    return len;
+  }
+  return len;
+}
+
+#endif
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 50f7f97581b..0622b140a5d 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -223,7 +223,11 @@ get_user_pass_cr(struct user_pass *up,
             if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0)
             {
                 /* Read username first */
+                #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+                if (fuzz_fgets(up->username, USER_PASS_LEN, fp) == NULL)
+                #else
                 if (fgets(up->username, USER_PASS_LEN, fp) == NULL)
+                #endif
                 {
                     msg(M_FATAL, "Error reading username from %s authfile: %s",
                         prefix,
@@ -232,7 +236,11 @@ get_user_pass_cr(struct user_pass *up,
             }
             chomp(up->username);
 
+            #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            if (fuzz_fgets(password_buf, USER_PASS_LEN, fp) != NULL)
+            #else
             if (fgets(password_buf, USER_PASS_LEN, fp) != NULL)
+            #endif
             {
                 chomp(password_buf);
             }
@@ -775,7 +783,9 @@ output_peer_info_env(struct env_set *es, const char *peer_info)
         }
         else
         {
+            #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
             msg(M_WARN, "validation failed on peer_info line received from client");
+            #endif
         }
     }
 }
diff --git a/src/openvpn/mroute.c b/src/openvpn/mroute.c
index 64404cdb6d4..45fc5516a89 100644
--- a/src/openvpn/mroute.c
+++ b/src/openvpn/mroute.c
@@ -206,9 +206,11 @@ mroute_extract_addr_ip(struct mroute_addr *src, struct mroute_addr *dest,
                 }
                 break;
 
+            #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
             default:
                 msg(M_WARN, "IP packet with unknown IP version=%d seen",
                     OPENVPN_IPH_GET_VER(*BPTR(buf)));
+            #endif
         }
     }
     return ret;
diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c
index 15e21452b6f..cd2cbc3e272 100644
--- a/src/openvpn/openvpn.c
+++ b/src/openvpn/openvpn.c
@@ -392,3 +392,7 @@ main(int argc, char *argv[])
     return openvpn_main(argc, argv);
 }
 #endif /* ifdef _WIN32 */
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#include "fake_fuzz_header.h"
+#endif
diff --git a/src/openvpn/packet_id.c b/src/openvpn/packet_id.c
index 1872bd13fb3..5340eeb80a9 100644
--- a/src/openvpn/packet_id.c
+++ b/src/openvpn/packet_id.c
@@ -494,7 +494,11 @@ packet_id_persist_save(struct packet_id_persist *p)
         seek_ret = lseek(p->fd, (off_t)0, SEEK_SET);
         if (seek_ret == (off_t)0)
         {
+            #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            n = fuzz_write(p->fd, &image, sizeof(image));
+            #else
             n = write(p->fd, &image, sizeof(image));
+            #endif
             if (n == sizeof(image))
             {
                 p->time_last_written = p->time;
diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c
index ed7201616a4..80a04e44eee 100644
--- a/src/openvpn/proxy.c
+++ b/src/openvpn/proxy.c
@@ -40,6 +40,9 @@
 #include "httpdigest.h"
 #include "ntlm.h"
 #include "memdbg.h"
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#include "fuzz_header.h"
+#endif
 #include "forward.h"
 
 #define UP_TYPE_PROXY        "HTTP Proxy"
@@ -97,7 +100,11 @@ recv_line(socket_descriptor_t sd,
         tv.tv_sec = timeout_sec;
         tv.tv_usec = 0;
 
+        #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        status = fuzz_select(sd + 1, &reads, NULL, NULL, &tv);
+        #else
         status = select(sd + 1, &reads, NULL, NULL, &tv);
+        #endif
 
         get_signal(signal_received);
         if (*signal_received)
@@ -126,7 +133,11 @@ recv_line(socket_descriptor_t sd,
         }
 
         /* read single char */
+        #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        size = fuzz_recv(sd, &c, 1, MSG_NOSIGNAL);
+        #else
         size = recv(sd, &c, 1, MSG_NOSIGNAL);
+        #endif
 
         /* error? */
         if (size != 1)
@@ -196,7 +207,11 @@ static bool
 send_line(socket_descriptor_t sd,
           const char *buf)
 {
+    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    const ssize_t size = fuzz_send(sd, buf, strlen(buf), MSG_NOSIGNAL);
+    #else
     const ssize_t size = send(sd, buf, strlen(buf), MSG_NOSIGNAL);
+    #endif
     if (size != (ssize_t) strlen(buf))
     {
         msg(D_LINK_ERRORS | M_ERRNO, "send_line: TCP port write failed on send()");
@@ -772,7 +787,12 @@ establish_http_proxy_passthru(struct http_proxy_info *p,
                 buf2[128] = 0; /* we only need the beginning - ensure it's null terminated. */
 
                 /* check for "Proxy-Authenticate: NTLM TlRM..." */
+                #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+                // this condition is hard to pass for fuzzer as the loop consumes a lot of input
+                if (true)
+                #else
                 if (nparms == 1)
+                #endif
                 {
                     /* parse buf2 */
                     msg(D_PROXY, "auth string: '%s'", buf2);
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 4a982561914..72ece81668d 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -3234,7 +3234,11 @@ link_socket_read_tcp(struct link_socket *sock,
 #else
         struct buffer frag;
         stream_buf_get_next(&sock->stream_buf, &frag);
+        #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        len = fuzz_recv(sock->sd, BPTR(&frag), BLEN(&frag), MSG_NOSIGNAL);
+        #else
         len = recv(sock->sd, BPTR(&frag), BLEN(&frag), MSG_NOSIGNAL);
+        #endif
 #endif
 
         if (!len)
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h
index 462afa31bb4..a5a33249115 100644
--- a/src/openvpn/socket.h
+++ b/src/openvpn/socket.h
@@ -34,6 +34,11 @@
 #include "proxy.h"
 #include "socks.h"
 #include "misc.h"
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+extern size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen);
+#endif
+
 #include "tun.h"
 
 /*
@@ -1157,7 +1162,11 @@ link_socket_write_udp_posix(struct link_socket *sock,
     }
     else
 #endif
+    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    return fuzz_sendto(sock->sd, BPTR(buf), BLEN(buf), 0,
+    #else
     return sendto(sock->sd, BPTR(buf), BLEN(buf), 0,
+    #endif
                   (struct sockaddr *) &to->dest.addr.sa,
                   (socklen_t) af_addr_size(to->dest.addr.sa.sa_family));
 }