From 56787c0c03b8db7af487d0efd18ee44242fd9197 Mon Sep 17 00:00:00 2001 From: Pengyu Chen Date: Sun, 17 Sep 2023 03:55:54 +0000 Subject: [PATCH] fuzz/*: fuzz rats-tls APIs in host mode use libfuzzer to fuzz rats-tls API `rats_tls_init()`, `rats_tls_negotiate()`,`rats_tls_transmit()` and `rats_tls_receive()` in host mode Signed-off-by: Pengyu Chen --- CMakeLists.txt | 6 + fuzz/CMakeLists.txt | 4 + fuzz/README.md | 60 +++++++++ fuzz/tls_init/CMakeLists.txt | 25 ++++ fuzz/tls_init/fuzz_init.cc | 113 +++++++++++++++++ fuzz/tls_negotiate/CMakeLists.txt | 26 ++++ fuzz/tls_negotiate/fuzz_negotiate.cc | 163 ++++++++++++++++++++++++ fuzz/tls_server/CMakeLists.txt | 26 ++++ fuzz/tls_server/fuzz_server.cc | 153 ++++++++++++++++++++++ fuzz/tls_transmit/CMakeLists.txt | 28 +++++ fuzz/tls_transmit/fuzz_transmit.cc | 182 +++++++++++++++++++++++++++ 11 files changed, 786 insertions(+) create mode 100644 fuzz/CMakeLists.txt create mode 100644 fuzz/README.md create mode 100644 fuzz/tls_init/CMakeLists.txt create mode 100644 fuzz/tls_init/fuzz_init.cc create mode 100644 fuzz/tls_negotiate/CMakeLists.txt create mode 100644 fuzz/tls_negotiate/fuzz_negotiate.cc create mode 100644 fuzz/tls_server/CMakeLists.txt create mode 100644 fuzz/tls_server/fuzz_server.cc create mode 100644 fuzz/tls_transmit/CMakeLists.txt create mode 100644 fuzz/tls_transmit/fuzz_transmit.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 388a34ff..a6585fba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ list(GET VERSION_LIST 2 VERSION_PATCH) option(BUILD_SAMPLES "Compile sample code along with libraries" ON) option(SGX_HW "Run SGX on hardware, OFF for simulation" ON) option(SGX_LVI_MITIGATION "Mitigation flag, default on" ON) +option(BUILD_FUZZ "Use lib-fuzzer to fuzz the code, default OFF" OFF) # Define build mode set(RATS_TLS_BUILD_MODE "host" @@ -102,6 +103,11 @@ if(BUILD_SAMPLES) add_subdirectory(samples) endif() +if(BUILD_FUZZ) + message(STATUS "Build Fuzz: on") + add_subdirectory(fuzz) +endif() + # Uninstall target if(NOT TARGET uninstall) configure_file( diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt new file mode 100644 index 00000000..de3d568c --- /dev/null +++ b/fuzz/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(tls_init) +add_subdirectory(tls_negotiate) +add_subdirectory(tls_server) +add_subdirectory(tls_transmit) \ No newline at end of file diff --git a/fuzz/README.md b/fuzz/README.md new file mode 100644 index 00000000..8470cb03 --- /dev/null +++ b/fuzz/README.md @@ -0,0 +1,60 @@ +# Building + +## Build Requirements +Note that `LibFuzzer` is part of `clang`, LibFuzzer is an in-process, coverage-guided, evolutionary fuzzing engine. +`LibFuzzer` is linked with the library under test, and feeds fuzzed inputs to the library via a specific fuzzing entrypoint (aka “target function”); the fuzzer then tracks which areas of the code are reached, and generates mutations on the corpus of input data in order to maximize the code coverage. + +Follow these steps to install clang: ++ Debian / Ubuntu: + +```shell +apt install -y clang +``` + ++ CentOS / RHEL / Fedora: + +```shell +yum install -y clang +``` + +## Build and Install +To build fuzzer program, just add `-DBUILD_FUZZ=on` option is enough, then you would see fuzz program in `/usr/share/rats-tls/fuzz`. + +```shell +cmake -DRATS_TLS_BUILD_MODE="host" -DBUILD_SAMPLES=on -DBUILD_FUZZ=on -H. -Bbuild +make -C build install +``` + +# FUZZ + +## rats_tls_init API +To fuzz `rats_tls_init()`, we use random input `* data` to fill the `conf`, and set value to part of the `conf` in order to run `rats_tls_init()` more frequently. +```bash +cd /usr/share/rats-tls/fuzz/ +mkdir corpus && cd corpus # create corpus dir +base64 /dev/urandom | head -c 1500000 > c1 # fill in corpus with random string +cd .. +./fuzz_init -max_len=1500000 -len_control=0 corpus # len_control=0 means try genarating input with size up to max_len +``` + +## rats_tls_negotiate API +Start the `/usr/share/rats_tls/fuzz/fuzz_server` first, then use `tls_negotiate` to connect to server and fuzz the `rats_tls_negotiate()` API. +```bash +cd /usr/share/rats_tls/fuzz/ +mkdir corpus && cd corpus # create corpus dir +base64 /dev/urandom | head -c 1500000 > c1 # fill in corpus with random string +cd .. +./fuzz_server & +./fuzz_negotiate -max_len=1500000 -len_control=0 corpus # len_control=0 means try genarating input with size up to max_len +``` + +## rats_tls_transmit / rats_tls_recv / rats_tls_cleanup +We synthesis the 3 sequential API in one program, start the `/usr/share/rats_tls/fuzz/fuzz_server` first, then use `tls_transmit` to connect to server and fuzz the `rats_tls_transmit()` and `rats_tls_recv()`,`rats_tls_cleanup` APIs by sending ramdom string and receiving the same response. +```shell +cd /usr/share/rats_tls/fuzz/ +mkdir corpus && cd corpus # create corpus dir and fill in random string +base64 /dev/urandom | head -c 1500000 > c1 +cd .. +./fuzz_server & +./fuzz_transmit -max_len=1500000 -len_control=0 corpus # len_control=0 means try genarating input with size up to max_len +``` \ No newline at end of file diff --git a/fuzz/tls_init/CMakeLists.txt b/fuzz/tls_init/CMakeLists.txt new file mode 100644 index 00000000..81360160 --- /dev/null +++ b/fuzz/tls_init/CMakeLists.txt @@ -0,0 +1,25 @@ +project(fuzz_init CXX) + +set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) +set(CMAKE_CXX_COMPILER "/usr/bin/clang++") +set(CMAKE_CXX_FLAGS "-fsanitize=address,fuzzer -g -fPIE ${CMAKE_CXX_FLAGS}") + +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include/rats-tls + ${RATS_TLS_INSTALL_INCLUDE_PATH} + ) +set(LIBRARY_DIRS ${RATS_TLS_INSTALL_LIB_PATH}) +set(RATS_TLS_INSTALL_FUZZ_PATH /usr/share/rats-tls/fuzz) + +include_directories(${INCLUDE_DIRS}) +link_directories(${LIBRARY_DIRS}) + +# Set source file +set(SOURCES fuzz_init.cc) + +# Generate bin file +add_executable(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} rats_tls) + +install(TARGETS ${PROJECT_NAME} + DESTINATION ${RATS_TLS_INSTALL_FUZZ_PATH}) diff --git a/fuzz/tls_init/fuzz_init.cc b/fuzz/tls_init/fuzz_init.cc new file mode 100644 index 00000000..4ddb3f66 --- /dev/null +++ b/fuzz/tls_init/fuzz_init.cc @@ -0,0 +1,113 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2021 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ +extern "C" { +#include +#include +#include +#include "rats-tls/api.h" +#include "rats-tls/log.h" +#include "rats-tls/claim.h" +#include "internal/core.h" +} +#include +#include + +#define CUSTOM_CLAIMS_SIZE 10 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + rats_tls_conf_t conf; // consume 192 bytes + if (size < sizeof(rats_tls_conf_t) + 10 * sizeof(claim_t) + 50 * 10 + 100) { + return 0; + } + FuzzedDataProvider fuzzed_data(data + sizeof(conf), size - sizeof(conf)); + + char attester_types[10][25] = { "nullattester", "", "sgx_la", "csv", + "sev", "sev_snp", "tdx_ecdsa", "sgx_ecdsa" }; + strcpy(attester_types[8], fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int i = 0; i < 9; i++) { + char verifier_types[10][25] = { "nullverifier", "", "sgx_la", + "csv", "sev", "sev_snp", + "tdx_ecdsa", "tdx_ecdsa", "sgx_ecdsa_qve" }; + strcpy(verifier_types[9], fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int j = 0; j < 10; j++) { + char tls_types[4][25] = { "nulltls", "", "openssl" }; + strcpy(tls_types[3], + fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int k = 0; k < 4; k++) { + char crypto_types[4][25] = { "nullcrypto", "", "openssl" }; + strcpy(crypto_types[3], + fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int l = 0; l < 4; l++) { + memcpy(&conf, + fuzzed_data.ConsumeBytes(sizeof(conf)) + .data(), + sizeof(conf)); + conf.log_level = RATS_TLS_LOG_LEVEL_DEFAULT; + conf.api_version = 0; + + strcpy(conf.attester_type, attester_types[i]); + strcpy(conf.verifier_type, verifier_types[j]); + strcpy(conf.tls_type, tls_types[k]); + strcpy(conf.crypto_type, crypto_types[l]); + + conf.cert_algo = RATS_TLS_CERT_ALGO_DEFAULT; + conf.flags = fuzzed_data.ConsumeIntegral(); + + claim_t custom_claims[CUSTOM_CLAIMS_SIZE]; + std::vector str_lists; + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + std::vector vec_str = + fuzzed_data.ConsumeBytesWithTerminator( + 50, '\0'); + std::string str(vec_str.begin(), vec_str.end()); + str_lists.push_back(str); + custom_claims[c].value = + (uint8_t *)str_lists[c].c_str(); + custom_claims[c].value_size = + (strlen(str_lists[c].c_str()) + 1) * + sizeof(char); + if (fuzzed_data.remaining_bytes() <= 0) { + for (int p = 0; p < c;p++) { + free(custom_claims[p].name); + } + return 0; + } + custom_claims[c].name = (char *)malloc(15); + strcpy(custom_claims[c].name, + fuzzed_data.ConsumeBytesAsString(10).c_str()); + } + conf.custom_claims = (claim_t *)custom_claims; + conf.custom_claims_length = CUSTOM_CLAIMS_SIZE; + rats_tls_handle handle; + rats_tls_err_t err = rats_tls_init(&conf, &handle); + + // free memory + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + free(custom_claims[c].name); + } + err = rats_tls_cleanup(handle); + if (err != RATS_TLS_ERR_NONE) + RTLS_ERR("Failed to cleanup %#x\n", err); + } + } + } + } + + return 0; +} \ No newline at end of file diff --git a/fuzz/tls_negotiate/CMakeLists.txt b/fuzz/tls_negotiate/CMakeLists.txt new file mode 100644 index 00000000..b0736cd1 --- /dev/null +++ b/fuzz/tls_negotiate/CMakeLists.txt @@ -0,0 +1,26 @@ +project(fuzz_negotiate CXX) + +set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) +set(CMAKE_CXX_COMPILER "/usr/bin/clang++") +set(CMAKE_CXX_FLAGS "-fsanitize=address,fuzzer -g -fPIE ${CMAKE_CXX_FLAGS}") + +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include/rats-tls + ${RATS_TLS_INSTALL_INCLUDE_PATH} + ) +set(LIBRARY_DIRS ${RATS_TLS_INSTALL_LIB_PATH}) +set(RATS_TLS_INSTALL_FUZZ_PATH /usr/share/rats-tls/fuzz) + +include_directories(${INCLUDE_DIRS}) +link_directories(${LIBRARY_DIRS}) + +# Set source file +set(SOURCES fuzz_negotiate.cc) + +# Generate bin file +add_executable(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} rats_tls) + +install(TARGETS ${PROJECT_NAME} + DESTINATION ${RATS_TLS_INSTALL_FUZZ_PATH}) + diff --git a/fuzz/tls_negotiate/fuzz_negotiate.cc b/fuzz/tls_negotiate/fuzz_negotiate.cc new file mode 100644 index 00000000..92907ce2 --- /dev/null +++ b/fuzz/tls_negotiate/fuzz_negotiate.cc @@ -0,0 +1,163 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2021 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include "rats-tls/api.h" +#include "rats-tls/log.h" +#include "rats-tls/claim.h" +#include "internal/core.h" +#include "internal/crypto_wrapper.h" +#include "internal/attester.h" +#include "internal/verifier.h" +#include "internal/tls_wrapper.h" +} +#include + +#define FUZZ_IP "127.0.0.1" +#define FUZZ_PORT 1234 +#define CUSTOM_CLAIMS_SIZE 10 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < sizeof(rats_tls_conf_t) + 10 * sizeof(claim_t) + 50 * 10 + 100) { + return 0; + } + + rats_tls_conf_t conf; // consume 192 bytes + FuzzedDataProvider fuzzed_data(data + sizeof(conf), size - sizeof(conf)); + + char attester_types[10][25] = { "nullattester", "", "sgx_la", "csv", + "sev", "sev_snp", "tdx_ecdsa", "sgx_ecdsa" }; + strcpy(attester_types[8], fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int i = 0; i < 9; i++) { + char verifier_types[10][25] = { "nullverifier", "", "sgx_la", + "csv", "sev", "sev_snp", + "tdx_ecdsa", "tdx_ecdsa", "sgx_ecdsa_qve" }; + strcpy(verifier_types[9], fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int j = 0; j < 10; j++) { + char tls_types[4][25] = { "nulltls", "", "openssl" }; + strcpy(tls_types[3], + fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int k = 0; k < 4; k++) { + char crypto_types[4][25] = { "nullcrypto", "", "openssl" }; + strcpy(crypto_types[3], + fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int l = 0; l < 4; l++) { + memcpy(&conf, + fuzzed_data.ConsumeBytes(sizeof(conf)) + .data(), + sizeof(conf)); + conf.log_level = RATS_TLS_LOG_LEVEL_DEFAULT; + conf.api_version = 0; + + strcpy(conf.attester_type, attester_types[i]); + strcpy(conf.verifier_type, verifier_types[j]); + strcpy(conf.tls_type, tls_types[k]); + strcpy(conf.crypto_type, crypto_types[l]); + + conf.cert_algo = RATS_TLS_CERT_ALGO_DEFAULT; + conf.flags = fuzzed_data.ConsumeIntegral(); + + claim_t custom_claims[CUSTOM_CLAIMS_SIZE]; + std::vector str_lists; + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + std::vector vec_str = + fuzzed_data.ConsumeBytesWithTerminator( + 50, '\0'); + std::string str(vec_str.begin(), vec_str.end()); + str_lists.push_back(str); + custom_claims[c].value = + (uint8_t *)str_lists[c].c_str(); + custom_claims[c].value_size = + (strlen(str_lists[c].c_str()) + 1) * + sizeof(char); + if (fuzzed_data.remaining_bytes() <= 0) { + for (int p = 0; p < c; p++) { + free(custom_claims[p].name); + } + return 0; + } + + custom_claims[c].name = (char *)malloc(15); + strcpy(custom_claims[c].name, + fuzzed_data.ConsumeBytesAsString(10).c_str()); + } + conf.custom_claims = (claim_t *)custom_claims; + conf.custom_claims_length = CUSTOM_CLAIMS_SIZE; + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + // free memory + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + free(custom_claims[c].name); + } + continue; + } + + struct sockaddr_in s_addr; + memset(&s_addr, 0, sizeof(s_addr)); + s_addr.sin_family = AF_INET; + s_addr.sin_port = htons(FUZZ_PORT); + + if (inet_pton(AF_INET, FUZZ_IP, &s_addr.sin_addr) != 1) { + // free memory + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + free(custom_claims[c].name); + } + continue; + } + + if (connect(sockfd, (struct sockaddr *)&s_addr, + sizeof(s_addr)) == -1) { + // free memory + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + free(custom_claims[c].name); + } + continue; + } + + rats_tls_handle handle; + rats_tls_err_t err = rats_tls_init(&conf, &handle); + if (err != RATS_TLS_ERR_NONE) { + // free memory + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + free(custom_claims[c].name); + } + continue; + } + rats_tls_negotiate(handle, sockfd); + + // free memory + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + free(custom_claims[c].name); + } + } + } + } + } + + return 0; +} \ No newline at end of file diff --git a/fuzz/tls_server/CMakeLists.txt b/fuzz/tls_server/CMakeLists.txt new file mode 100644 index 00000000..993260a6 --- /dev/null +++ b/fuzz/tls_server/CMakeLists.txt @@ -0,0 +1,26 @@ +project(fuzz_server CXX) + +set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) +set(CMAKE_CXX_COMPILER "/usr/bin/clang++") +set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") + +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include/rats-tls + ${RATS_TLS_INSTALL_INCLUDE_PATH} + ) +set(LIBRARY_DIRS ${RATS_TLS_INSTALL_LIB_PATH}) +set(RATS_TLS_INSTALL_FUZZ_PATH /usr/share/rats-tls/fuzz) + +include_directories(${INCLUDE_DIRS}) +link_directories(${LIBRARY_DIRS}) + +# Set source file +set(SOURCES fuzz_server.cc) + +# Generate bin file +add_executable(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} rats_tls) + +install(TARGETS ${PROJECT_NAME} + DESTINATION ${RATS_TLS_INSTALL_FUZZ_PATH}) + diff --git a/fuzz/tls_server/fuzz_server.cc b/fuzz/tls_server/fuzz_server.cc new file mode 100644 index 00000000..3672bde2 --- /dev/null +++ b/fuzz/tls_server/fuzz_server.cc @@ -0,0 +1,153 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2021 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-1.0 + */ + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rats-tls/api.h" +#include "rats-tls/log.h" +#include "rats-tls/claim.h" +#include "internal/core.h" +#include "internal/crypto_wrapper.h" +#include "internal/attester.h" +#include "internal/verifier.h" +#include "internal/tls_wrapper.h" +} +#define FUZZ_IP "127.0.0.1" +#define FUZZ_PORT 1234 + +int main() +{ + rats_tls_conf_t conf; + + memset(&conf, 0, sizeof(conf)); + conf.log_level = RATS_TLS_LOG_LEVEL_INFO; + strcpy(conf.attester_type, "nullattester"); + strcpy(conf.verifier_type, "nullverifier"); + strcpy(conf.tls_type, "nulltls"); + strcpy(conf.crypto_type, "nullcrypto"); + + /* Optional: Set some user-defined custom claims, which will be embedded in the certificate. */ + claim_t custom_claims[2] = { + { .name = "key_0", .value = (uint8_t *)"value_0", .value_size = sizeof("value_0") }, + { .name = "key_1", .value = (uint8_t *)"value_1", .value_size = sizeof("value_1") }, + }; + conf.custom_claims = (claim_t *)custom_claims; + conf.custom_claims_length = 2; + + conf.cert_algo = RATS_TLS_CERT_ALGO_DEFAULT; + conf.flags |= RATS_TLS_CONF_FLAGS_SERVER; + conf.flags |= RATS_TLS_CONF_FLAGS_MUTUAL; + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + RTLS_ERR("fail to create socket\n"); + return -1; + } + + int reuse = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuse, sizeof(int)) < 0) { + RTLS_ERR("Failed to call setsockopt()"); + return -1; + } + + /* Set keepalive options */ + int flag = 1; + int tcp_keepalive_time = 1; + int tcp_keepalive_intvl = 1; + int tcp_keepalive_probes = 5; + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag)) < 0) { + RTLS_ERR("Failed to call setsockopt()"); + return -1; + } + if (setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepalive_time, + sizeof(tcp_keepalive_time)) < 0) { + RTLS_ERR("Failed to call setsockopt()"); + return -1; + } + if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepalive_intvl, + sizeof(tcp_keepalive_intvl)) < 0) { + RTLS_ERR("Failed to call setsockopt()"); + return -1; + } + if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &tcp_keepalive_probes, + sizeof(tcp_keepalive_probes)) < 0) { + RTLS_ERR("Failed to call setsockopt()"); + return -1; + } + + struct sockaddr_in s_addr; + memset(&s_addr, 0, sizeof(s_addr)); + s_addr.sin_family = AF_INET; + s_addr.sin_addr.s_addr = inet_addr(FUZZ_IP); + s_addr.sin_port = htons(FUZZ_PORT); + + /* Bind the server socket */ + if (bind(sockfd, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1) { + return -1; + } + + /* Listen for a new connection, allow 5 pending connections */ + if (listen(sockfd, 5) == -1) { + return -1; + } + + rats_tls_handle handle; + rats_tls_err_t ret = rats_tls_init(&conf, &handle); + if (ret != RATS_TLS_ERR_NONE) { + return -1; + } + + ret = rats_tls_set_verification_callback(&handle, NULL); + if (ret != RATS_TLS_ERR_NONE) { + return -1; + } + + RTLS_INFO("waiting for socket connection\n"); + while (1) { + /* Accept client connections */ + struct sockaddr_in c_addr; + socklen_t size = sizeof(c_addr); + + int connd = accept(sockfd, (struct sockaddr *)&c_addr, &size); + if (connd < 0) { + return 0; + } + RTLS_INFO("Receive socket connection\n"); + + ret = rats_tls_negotiate(handle, connd); + if (ret != RATS_TLS_ERR_NONE) { + RTLS_ERR("negotiate failed \n"); + return 0; + } + RTLS_INFO("Negotiate successfully\n"); + + char buf[256]; + size_t len = sizeof(buf); + ret = rats_tls_receive(handle, buf, &len); + if (ret != RATS_TLS_ERR_NONE) { + RTLS_ERR("Receive failed \n"); + continue; + } + len = sizeof(buf) - 1; + buf[len] = '\0'; + RTLS_INFO("The str is %s\n", buf); + + ret = rats_tls_transmit(handle, buf, &len); + if (ret != RATS_TLS_ERR_NONE) { + continue; + } + close(connd); + } + return 0; +} \ No newline at end of file diff --git a/fuzz/tls_transmit/CMakeLists.txt b/fuzz/tls_transmit/CMakeLists.txt new file mode 100644 index 00000000..a2b64956 --- /dev/null +++ b/fuzz/tls_transmit/CMakeLists.txt @@ -0,0 +1,28 @@ +project(fuzz_transmit CXX) + +set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) +set(CMAKE_CXX_COMPILER "/usr/bin/clang++") +set(CMAKE_CXX_FLAGS "-fsanitize=address,fuzzer -g -fPIE ${CMAKE_CXX_FLAGS}") + + + +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include/rats-tls + ${RATS_TLS_INSTALL_INCLUDE_PATH} + ) +set(LIBRARY_DIRS ${RATS_TLS_INSTALL_LIB_PATH}) +set(RATS_TLS_INSTALL_FUZZ_PATH /usr/share/rats-tls/fuzz) + +include_directories(${INCLUDE_DIRS}) +link_directories(${LIBRARY_DIRS}) + +# Set source file +set(SOURCES fuzz_transmit.cc) + +# Generate bin file +add_executable(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} rats_tls) + +install(TARGETS ${PROJECT_NAME} + DESTINATION ${RATS_TLS_INSTALL_FUZZ_PATH}) + diff --git a/fuzz/tls_transmit/fuzz_transmit.cc b/fuzz/tls_transmit/fuzz_transmit.cc new file mode 100644 index 00000000..958dd055 --- /dev/null +++ b/fuzz/tls_transmit/fuzz_transmit.cc @@ -0,0 +1,182 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2021 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.1 + */ + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include "rats-tls/api.h" +#include "rats-tls/log.h" +#include "rats-tls/claim.h" +} +#include +#define FUZZ_IP "127.0.0.1" +#define FUZZ_PORT 1234 +#define CUSTOM_CLAIMS_SIZE 10 + +int user_callback(void *args) +{ + rtls_evidence_t *ev = (rtls_evidence_t *)args; + + printf("verify_callback called, claims %p, claims_size %zu, args %p\n", ev->custom_claims, + ev->custom_claims_length, args); + for (size_t i = 0; i < ev->custom_claims_length; ++i) { + printf("custom_claims[%zu] -> name: '%s' value_size: %zu value: '%.*s'\n", i, + ev->custom_claims[i].name, ev->custom_claims[i].value_size, + (int)ev->custom_claims[i].value_size, ev->custom_claims[i].value); + } + return 1; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < sizeof(rats_tls_conf_t) + 10 * sizeof(claim_t) + 50 * 10 + 100) { + return 0; + } + FuzzedDataProvider fuzzed_data(data + sizeof(rats_tls_conf_t), + size - sizeof(rats_tls_conf_t)); + + char attester_types[10][25] = { "nullattester", "", "sgx_la", "csv", + "sev", "sev_snp", "tdx_ecdsa", "sgx_ecdsa" }; + strcpy(attester_types[8], fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int i = 0; i < 9; i++) { + char verifier_types[10][25] = { "nullverifier", "", "sgx_la", + "csv", "sev", "sev_snp", + "tdx_ecdsa", "tdx_ecdsa", "sgx_ecdsa_qve" }; + strcpy(verifier_types[9], fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int j = 0; j < 10; j++) { + char tls_types[4][25] = { "nulltls", "", "openssl" }; + strcpy(tls_types[3], + fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int k = 0; k < 4; k++) { + char crypto_types[4][25] = { "nullcrypto", "", "openssl" }; + strcpy(crypto_types[3], + fuzzed_data.ConsumeBytesWithTerminator(20, '\0').data()); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + for (int l = 0; l < 4; l++) { + rats_tls_conf_t conf; + memcpy(&conf, + fuzzed_data.ConsumeBytes(sizeof(conf)) + .data(), + sizeof(conf)); + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + conf.log_level = RATS_TLS_LOG_LEVEL_INFO; + conf.cert_algo = RATS_TLS_CERT_ALGO_DEFAULT; + conf.api_version = 0; + conf.flags = fuzzed_data.ConsumeIntegral(); + + strcpy(conf.attester_type, attester_types[i]); + strcpy(conf.verifier_type, verifier_types[j]); + strcpy(conf.tls_type, tls_types[k]); + strcpy(conf.crypto_type, crypto_types[l]); + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + RTLS_ERR("socked create failed \n"); + continue; + } + + claim_t custom_claims[CUSTOM_CLAIMS_SIZE]; + std::vector str_lists; + for (int c = 0; c < CUSTOM_CLAIMS_SIZE; c++) { + std::vector vec_str = + fuzzed_data.ConsumeBytesWithTerminator( + 50, '\0'); + std::string str(vec_str.begin(), vec_str.end()); + str_lists.push_back(str); + custom_claims[c].value = + (uint8_t *)str_lists[c].c_str(); + custom_claims[c].value_size = + (strlen(str_lists[c].c_str()) + 1) * + sizeof(char); + if (fuzzed_data.remaining_bytes() <= 0) { + return 0; + } + custom_claims[c].name = "key"; + } + conf.custom_claims = (claim_t *)custom_claims; + conf.custom_claims_length = CUSTOM_CLAIMS_SIZE; + + struct sockaddr_in s_addr; + memset(&s_addr, 0, sizeof(s_addr)); + s_addr.sin_family = AF_INET; + s_addr.sin_port = htons(FUZZ_PORT); + + if (inet_pton(AF_INET, FUZZ_IP, &s_addr.sin_addr) != 1) { + continue; + } + + if (connect(sockfd, (struct sockaddr *)&s_addr, + sizeof(s_addr)) == -1) { + close(sockfd); + continue; + } + + rats_tls_handle handle; + rats_tls_err_t err = rats_tls_init(&conf, &handle); + if (err != RATS_TLS_ERR_NONE) { + continue; + } + + err = rats_tls_set_verification_callback(&handle, + user_callback); + if (err != RATS_TLS_ERR_NONE) { + RTLS_ERR( + "Failed to set verification callback %#x\n", + err); + continue; + } + RTLS_INFO("Before negotiate \n"); + err = rats_tls_negotiate(handle, sockfd); + if (err != RATS_TLS_ERR_NONE) { + rats_tls_cleanup(handle); + continue; + } + + const char *msg = "ajh#jldsXoidjxdsa\n"; + + if (fuzzed_data.remaining_bytes() < 0) { + return 0; + } + RTLS_INFO("After nego, start transmit \n"); + + size_t len = strlen(msg); + err = rats_tls_transmit(handle, (void *)msg, &len); + if (err != RATS_TLS_ERR_NONE || len != strlen(msg)) { + RTLS_ERR("Failed to transmit %#x\n", err); + continue; + } + + char buf[256]; + len = sizeof(buf); + err = rats_tls_receive(handle, buf, &len); + if (err != RATS_TLS_ERR_NONE) { + continue; + } + } + } + } + } + return 0; +} \ No newline at end of file