From 4a1eb8753257cb61c39096b78c8cbf533bae8793 Mon Sep 17 00:00:00 2001 From: Dilkhush Purohit Date: Wed, 11 Mar 2026 22:57:18 +0530 Subject: [PATCH] add C implementation for httpbin api --- .gitignore | 1 + .gitmodules | 3 + CMakeLists.txt | 6 ++ LICENSE | 21 +++++ README.md | 24 ++++++ build.sh | 28 +++++++ httpbin/c/CMakeLists.txt | 11 +++ httpbin/c/main.c | 174 +++++++++++++++++++++++++++++++++++++++ mbedtls | 1 + 9 files changed, 269 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100755 build.sh create mode 100644 httpbin/c/CMakeLists.txt create mode 100644 httpbin/c/main.c create mode 160000 mbedtls diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c795b05 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..27944ef --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mbedtls"] + path = mbedtls + url = https://github.com/Mbed-TLS/mbedtls.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..db2de08 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.10) +project(MbedTLS Integration Example) + +add_subdirectory(mbedtls) + +add_subdirectory(httpbin/c) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0cb78a7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2026] [Dilkhush] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5de0243 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Mbed TLS Integration Examples + +Uses public APIs. + +## Build Steps + +1. **Clone the repository:** + ```bash + git clone https://git.kolibrios.org/DIlkhush00/Mbed-TLS-Integration-Examples.git + ``` +2. **Build:** + ```bash + cd Mbed-TLS-Integration-Examples + mkdir build && cd build + cmake .. + make + + # or just run the script + ./build.sh + ``` +3. **Run:** + ```bash + .// + ``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5f809e8 --- /dev/null +++ b/build.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status +set -e + +# Configurations +BUILD_DIR="build" +echo "=== Starting Build Process ===" + +# Clean existing build +if [ -d "$BUILD_DIR" ]; then + echo "Removing existing build directory..." + rm -rf "$BUILD_DIR" +fi + +# Create build directory +echo "Creating build directory..." +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" + +# Build the project +echo "Building project..." +cmake .. +make -j$(nproc) + +echo "" +echo "✓ Build Successful" +echo "Run the code with: ./build//_c" \ No newline at end of file diff --git a/httpbin/c/CMakeLists.txt b/httpbin/c/CMakeLists.txt new file mode 100644 index 0000000..84a6ce6 --- /dev/null +++ b/httpbin/c/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(httpbin_c main.c) + +target_link_libraries(httpbin_c + PRIVATE + mbedtls +) + +target_include_directories(httpbin_c + PRIVATE + ${MBEDTLS_SOURCE_DIR}/include +) diff --git a/httpbin/c/main.c b/httpbin/c/main.c new file mode 100644 index 0000000..b66cb52 --- /dev/null +++ b/httpbin/c/main.c @@ -0,0 +1,174 @@ +#include "mbedtls/platform.h" +#include "mbedtls/build_info.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#define SERVER_PORT "443" +#define SERVER_NAME "httpbin.org" +#define GET_REQUEST "GET /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n" +#define DEBUG_LEVEL 0 + +static void my_debug(void *ctx, int level, + const char *file, int line, const char *str) +{ + ((void) level); + mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str); + fflush((FILE *) ctx); +} + +int main(void) { + int ret; + ssize_t bytes_read; + unsigned char buf[1024]; + + mbedtls_net_context server_fd; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + + mbedtls_printf("Initializing TLS structures..."); + fflush(stdout); + + mbedtls_net_init(&server_fd); + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + + mbedtls_printf(" ok\n"); + + mbedtls_printf("Initializing PSA Crypto..."); + fflush(stdout); + + psa_status_t psa_status = psa_crypto_init(); + if (psa_status != PSA_SUCCESS) { + mbedtls_printf(" failed\n ! psa_crypto_init failed: %d\n\n", (int)psa_status); + ret = -1; + goto exit; + } + + mbedtls_printf(" ok\n"); + + mbedtls_printf("Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT); + fflush(stdout); + + if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, + SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); + goto exit; + } + + if ((ret = mbedtls_net_set_block(&server_fd)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_net_set_block returned %d\n\n", ret); + goto exit; + } + + mbedtls_printf(" ok\n"); + + mbedtls_printf("Configuring SSL/TLS..."); + fflush(stdout); + + if ((ret = mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret); + goto exit; + } + + mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); // for the demo purposes, not safe for prod + + mbedtls_debug_set_threshold(DEBUG_LEVEL); + mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); + + mbedtls_printf(" ok\n"); + + mbedtls_printf("Setting up SSL context..."); + fflush(stdout); + + if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret); + goto exit; + } + + // Sets SNI (important for servers hosting multiple domains on the same IP) + if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); + goto exit; + } + + mbedtls_printf(" ok\n"); + + mbedtls_printf("Binding socket to TLS..."); + fflush(stdout); + + mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + mbedtls_printf(" ok\n"); + + mbedtls_printf("Performing TLS handshake..."); + fflush(stdout); + + while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret); + goto exit; + } + } + + mbedtls_printf(" ok\n"); + mbedtls_printf("TLS version: %s\n", mbedtls_ssl_get_version(&ssl)); + mbedtls_printf("Cipher: %s\n\n", mbedtls_ssl_get_ciphersuite(&ssl)); + + + mbedtls_printf("Sending HTTP request..."); + fflush(stdout); + + size_t request_len = strlen(GET_REQUEST); + if ((ret = mbedtls_ssl_write(&ssl, (const unsigned char*)GET_REQUEST, request_len)) < 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret); + goto exit; + } + + mbedtls_printf(" ok (%d bytes)\n", ret); + + mbedtls_printf("Receiving response:\n\n"); + + int response_received = 0; + while ((bytes_read = mbedtls_ssl_read(&ssl, buf, sizeof(buf) - 1)) > 0) { + buf[bytes_read] = '\0'; + mbedtls_printf("%s", (char *)buf); + response_received = 1; + } + + if (bytes_read < 0) { + if (bytes_read == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + if (!response_received) { + mbedtls_printf("\n (Connection closed by server)\n"); + } + } else { + unsigned char error_buffer[256]; + mbedtls_strerror(bytes_read, (char *)error_buffer, sizeof(error_buffer)); + mbedtls_printf("\n ! mbedtls_ssl_read error (%d): %s\n", (int)bytes_read, error_buffer); + } + } + + + +exit: + mbedtls_printf("\n\nClosing TLS connection..."); + fflush(stdout); + + // do orderly cleanup + mbedtls_ssl_close_notify(&ssl); + mbedtls_net_free(&server_fd); + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + + mbedtls_printf(" ok\n\n"); + + return ret; +} \ No newline at end of file diff --git a/mbedtls b/mbedtls new file mode 160000 index 0000000..b5749b8 --- /dev/null +++ b/mbedtls @@ -0,0 +1 @@ +Subproject commit b5749b88f666e26a1ae3b7f1d55f70dec11cebb2