#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 "mbedtls/x509_crt.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 GET_REQUEST_IMAGE "GET /image HTTP/1.1\r\nHost: httpbin.org\r\naccept: image/webp\r\n\r\n" #define POST_BODY "name=makora&project=MbedTLS Integration Example" #define POST_REQUEST "POST /post HTTP/1.1\r\n" \ "Host: httpbin.org\r\n" \ "Content-Type: application/x-www-form-urlencoded\r\n" \ "Content-Length: 47\r\n" \ "Connection: close\r\n" \ "\r\n" \ POST_BODY #define DEBUG_LEVEL 0 #define CA_CERT_PATH "/etc/ssl/certs/ca-certificates.crt" // most distros use this path for CA certs, adjust if needed 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_x509_crt cacert; mbedtls_printf("Initializing TLS structures..."); fflush(stdout); mbedtls_net_init(&server_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); // mbedtls_x509_crt_init(&cacert); 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_printf("Loading CA certificate from %s...", CA_CERT_PATH); // fflush(stdout); // ret = mbedtls_x509_crt_parse_file(&cacert, CA_CERT_PATH); // if (ret != 0) { // mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n", -ret); // goto exit; // } // mbedtls_printf(" ok\n"); // mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); // mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); // no good 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(POST_REQUEST); if ((ret = mbedtls_ssl_write(&ssl, (const unsigned char*)POST_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"); // FILE *img_file = fopen("image.webp", "wb"); // if (img_file == NULL) { // mbedtls_printf(" failed\n ! Could not create image file\n\n"); // goto exit; // } // int skip_headers = 0; int res_recv = 0; while ((bytes_read = mbedtls_ssl_read(&ssl, buf, sizeof(buf) - 1)) > 0) { buf[bytes_read] = '\0'; // not needed for binary response mbedtls_printf("%s", (char *)buf); // unsigned char *data_to_write = buf; // size_t data_len = bytes_read; // if (!skip_headers) { // unsigned char *header_end = (unsigned char *)strstr((const char *)buf, "\r\n\r\n"); // if (header_end != NULL) { // data_to_write = header_end + 4; // +4 to skip the "\r\n\r\n" // data_len = bytes_read - (data_to_write - buf); // skip_headers = 1; // mbedtls_printf("Headers skipped, image data starts (%zu bytes in first chunk)\n", data_len); // } else { // continue; // } // } // size_t written = fwrite(data_to_write, 1, data_len, img_file); // if (written != data_len) { // mbedtls_printf(" failed\n ! Could not write to image file\n\n"); // fclose(img_file); // goto exit; // } res_recv = 1; } // fclose(img_file); if (bytes_read < 0) { if (bytes_read == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { if (res_recv) { mbedtls_printf("\nImage saved to image.webp\n"); } else { 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_x509_crt_free(&cacert); mbedtls_printf(" ok\n\n"); return ret; }