]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
fuzzer-verify-cert: add comments, refactor code in multiple functions for more readab...
authorGuido Vranken <guidovranken@gmail.com>
Thu, 10 Aug 2017 23:22:34 +0000 (01:22 +0200)
committerGuido Vranken <guidovranken@gmail.com>
Thu, 10 Aug 2017 23:22:34 +0000 (01:22 +0200)
src/openvpn/fuzzer-verify-cert.c

index 1b5861f830248c3fdc4572262c2eb5c6fd088db2..198e22716b269336864e495ba5377b97218a7f20 100644 (file)
@@ -33,146 +33,206 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
     SSL_load_error_strings();
     return 1;
 #else
+    /* Currently no PolarSSL/mbed TLS support */
 #error "This fuzzing target cannot be built"
 #endif
     return 1;
 }
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
-{
-    struct tls_session* session;
-    struct gc_arena gc;
-    unsigned int generic_uint;
-    ssize_t generic_ssizet;
-    ssize_t nid;
+
 #if defined(ENABLE_CRYPTO_OPENSSL)
-    X509* x509 = NULL;
+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;
+}
 #else
-    mbedtls_x509_crt x509;
+static int parse_x509(const uint8_t* data, size_t size, X509* out)
+{
+    mbedtls_x509_crt_init(x509);
+    if ( mbedtls_x509_crt_parse_der(x509, data, size) != 0 ) {
+        return -1;
+    }
+
+    return 0;
+}
 #endif
 
-    if ( size < SUBBUFFER_SIZE )
+static int init_session_opt(struct tls_options** _opt, struct gc_arena* gc)
+{
+    ssize_t nid;
+    ssize_t generic_ssizet;
+    struct tls_options* opt;
+
+    ALLOC_OBJ_GC(*_opt, struct tls_options, gc);
+    if ( opt == NULL )
     {
-        return 0;
+        goto cleanup;
     }
 
-    gc = gc_new();
+    opt = *_opt;
 
-    fuzzer_set_input((unsigned char*)data, size);
+    memset(opt, 0xFE, sizeof(struct tls_options));
 
-    data += SUBBUFFER_SIZE;
-    size -= SUBBUFFER_SIZE;
+    opt->es = env_set_create(gc);
+    opt->x509_username_field = NULL;
+    opt->remote_cert_eku = NULL;
 
-#if defined(ENABLE_CRYPTO_OPENSSL)
-    x509 = d2i_X509(NULL, (const unsigned char**)&data, size);
-    if ( x509 == NULL )
-    {
-        gc_free(&gc);
-        return 0;
-    }
-#else
-    mbedtls_x509_crt_init(&x509);
-    if ( mbedtls_x509_crt_parse_der(&x509, data, size) != 0 ) {
-        return 0;
-    }
-#endif
-    ALLOC_OBJ_GC(session, struct tls_session, &gc);
-    if ( session == NULL )
-    {
-        goto cleanup;
-    }
-    memset(session, 0xFE, sizeof(struct tls_session));
-    
-    ALLOC_OBJ_GC(session->opt, struct tls_options, &gc);
-    if ( session->opt == NULL )
-    {
-        goto cleanup;
-    }
-    memset(session->opt, 0xFE, sizeof(struct tls_options));
+    /* Prevents failure if x509 sha1 hashes do not match */
+    opt->verify_hash = NULL;
 
-    session->opt->es = env_set_create(&gc);
-    session->common_name = NULL;
-    session->opt->x509_username_field = NULL;
-    session->opt->remote_cert_eku = NULL;
-    FUZZER_GET_DATA(&generic_uint, sizeof(generic_uint));
+    /* Prevent attempt to run --tls-verify script */
+    opt->verify_command = NULL;
 
-    /* compat_flag() settings are accessed in string_mod_remap_name */
-    compat_flag(generic_uint);
+    /* Do not verify against CRL file */
+    opt->crl_file = NULL;
 
-    /* Accessed in server_untrusted() */
-    session->untrusted_addr.dest.addr.sa.sa_family = AF_UNSPEC;
+    /* Do not run --tls-verify plugins */
+    opt->plugins = NULL;
 
     FUZZER_GET_INTEGER(generic_ssizet, 1);
     switch ( generic_ssizet )
     {
         case    0:
             FUZZER_GET_INTEGER(nid, (sizeof(nidstrs)/sizeof(nidstrs[0])) - 1);
-            session->opt->x509_username_field = nidstrs[nid];
+            opt->x509_username_field = nidstrs[nid];
             break;
         case    1:
-            session->opt->x509_username_field = "ext:subjectAltName";
+            opt->x509_username_field = "ext:subjectAltName";
             break;
     }
 
-    /* Accessed in set_common_name() */
-    FUZZER_GET_STRING(session->common_name, 256);
-
-    /* Prevents failure if x509 sha1 hashes do not match */
-    session->opt->verify_hash = NULL;
-
-    /* Prevent attempt to run --tls-verify script */
-    session->opt->verify_command = NULL;
-
-    /* Do not verify against CRL file */
-    session->opt->crl_file = NULL;
-
-    /* Do not run --tls-verify plugins */
-    session->opt->plugins = NULL;
+    FUZZER_GET_INTEGER(generic_ssizet, 2);
+    switch ( generic_ssizet )
+    {
+        case    0:
+            opt->ns_cert_type = NS_CERT_CHECK_NONE;
+            break;
+        case    1:
+            opt->ns_cert_type = NS_CERT_CHECK_SERVER;
+            break;
+        case    2:
+            opt->ns_cert_type = NS_CERT_CHECK_CLIENT;
+            break;
+    }
 
     FUZZER_GET_INTEGER(generic_ssizet, 1);
     switch ( generic_ssizet )
     {
         case    0:
 #if defined(ENABLE_CRYPTO_OPENSSL)
-            session->opt->x509_track = NULL;
+            opt->x509_track = NULL;
 #else
-            ALLOC_OBJ_GC(session->opt->x509_track, struct x509_track, &gc);
-            if ( session->opt->x509_track == NULL )
+            ALLOC_OBJ_GC(opt->x509_track, struct x509_track, gc);
+            if ( opt->x509_track == NULL )
             {
                 goto cleanup;
             }
 #endif
             break;
         case    1:
-            session->opt->x509_track = NULL;
+            opt->x509_track = NULL;
             break;
     }
 
-    FUZZER_GET_INTEGER(generic_ssizet, 2);
+    FUZZER_GET_INTEGER(generic_ssizet, 1);
     switch ( generic_ssizet )
     {
         case    0:
-            session->opt->ns_cert_type = NS_CERT_CHECK_NONE;
+            opt->remote_cert_eku = NULL;
             break;
         case    1:
-            session->opt->ns_cert_type = NS_CERT_CHECK_SERVER;
-            break;
-        case    2:
-            session->opt->ns_cert_type = NS_CERT_CHECK_CLIENT;
-            break;
+            FUZZER_GET_STRING(opt->remote_cert_eku, 256);
     }
-    
-    FUZZER_GET_DATA(&session->opt->remote_cert_ku, sizeof(session->opt->remote_cert_ku));
 
-    FUZZER_GET_INTEGER(generic_ssizet, 1);
-    switch ( generic_ssizet )
+    FUZZER_GET_DATA(&(opt->remote_cert_ku), sizeof(opt->remote_cert_ku));
+
+    return 0;
+
+cleanup:
+    return -1;
+}
+
+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 )
+    {
+        goto cleanup;
+    }
+
+    session = *_session;
+
+    memset(session, 0xFE, sizeof(struct tls_session));
+
+    /* Accessed in set_common_name() */
+    FUZZER_GET_STRING(session->common_name, 256);
+
+    /* Initialize the session->opt structure */
+    if ( init_session_opt(&(session->opt), gc) == -1 ) {
+        goto cleanup;
+    }
+
+    /* Accessed in server_untrusted() */
+    session->untrusted_addr.dest.addr.sa.sa_family = AF_UNSPEC;
+
+
+    return 0;
+
+cleanup:
+    return -1;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    struct tls_session* session = NULL;
+    struct gc_arena gc;
+    unsigned int generic_uint;
+    ssize_t generic_ssizet;
+#if defined(ENABLE_CRYPTO_OPENSSL)
+    X509* x509 = NULL;
+#else
+    mbedtls_x509_crt x509;
+#endif
+
+    /* The first SUBBUFFER_SIZE bytes of data is the region of the
+     * fuzzer input from which data is culled to fill the
+     * tls_session struct.
+     *
+     * The remainder of the data is treated as an X509 certificate
+     */
+
+    if ( size < SUBBUFFER_SIZE )
     {
-    case    0:
-        session->opt->remote_cert_eku = NULL;
-        break;
-    case    1:
-        FUZZER_GET_STRING(session->opt->remote_cert_eku, 256);
+        return 0;
+    }
+
+    gc = gc_new();
+
+    fuzzer_set_input((unsigned char*)data, size);
+
+    data += SUBBUFFER_SIZE;
+    size -= SUBBUFFER_SIZE;
+
+    if ( parse_x509(data, size, &x509) == -1 ) {
+        gc_free(&gc);
+        return 0;
+    }
+
+    if ( init_session(&session, &gc) == -1 ) {
+        goto cleanup;
     }
 
+    /* compat_flag() settings are accessed in string_mod_remap_name */
+    FUZZER_GET_DATA(&generic_uint, sizeof(generic_uint));
+    compat_flag(generic_uint);
+
+
     FUZZER_GET_INTEGER(generic_ssizet, 256);
 #if defined(ENABLE_CRYPTO_OPENSSL)
     verify_cert(session, x509, generic_ssizet);
@@ -181,13 +241,24 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 #endif
 
 cleanup:
-    free(session->common_name);
-    free((void*)session->opt->remote_cert_eku);
+    if ( session ) {
+        /* common_name is the only session member that may contain
+         * malloc'ed data */
+        free(session->common_name);
+
+        /* remote_cert_eku is the only session->opt member that
+         * may contain malloc'ed data */
+        if ( session->opt ) {
+            free((void*)session->opt->remote_cert_eku);
+        }
+    }
+
 #if defined(ENABLE_CRYPTO_OPENSSL)
     X509_free(x509);
 #else
     mbedtls_x509_crt_free(&x509);
 #endif
+
     gc_free(&gc);
     return 0;
 }