{"id":25863847,"url":"https://github.com/mytechnotalent/ipts","last_synced_at":"2026-05-12T10:35:10.049Z","repository":{"id":279815447,"uuid":"940077004","full_name":"mytechnotalent/ipts","owner":"mytechnotalent","description":"IoT Pico W TLS Server that obtains the Pico W temperature and serves it to a TLS client where this project is designed for a MAC M series client and is based on the Raspberry Pi Foundation’s pico_examples TLS client example.","archived":false,"fork":false,"pushed_at":"2025-11-26T22:13:49.000Z","size":1299,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-29T17:34:07.932Z","etag":null,"topics":["iot","iot-application","iot-device","iot-framework","iot-platform","pico","picow","raspberry-pi","raspberry-pi-pico","raspberry-pi-pico-rp2040","raspberry-pi-pico-sdk","raspberry-pi-pico-w","raspberrypi"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mytechnotalent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-27T15:21:45.000Z","updated_at":"2025-11-26T22:13:53.000Z","dependencies_parsed_at":"2025-02-27T21:58:12.237Z","dependency_job_id":"63aa2da4-39f8-4b43-b6c6-b3356c1037ae","html_url":"https://github.com/mytechnotalent/ipts","commit_stats":null,"previous_names":["mytechnotalent/ipts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mytechnotalent/ipts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2Fipts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2Fipts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2Fipts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2Fipts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mytechnotalent","download_url":"https://codeload.github.com/mytechnotalent/ipts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2Fipts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32934754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T09:19:52.626Z","status":"ssl_error","status_checked_at":"2026-05-12T09:17:33.438Z","response_time":102,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["iot","iot-application","iot-device","iot-framework","iot-platform","pico","picow","raspberry-pi","raspberry-pi-pico","raspberry-pi-pico-rp2040","raspberry-pi-pico-sdk","raspberry-pi-pico-w","raspberrypi"],"created_at":"2025-03-02T00:26:44.529Z","updated_at":"2026-05-12T10:35:10.043Z","avatar_url":"https://github.com/mytechnotalent.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"![image](https://github.com/mytechnotalent/ipts/blob/main/ipts.png?raw=true)\n\n## FREE Reverse Engineering Self-Study Course [HERE](https://github.com/mytechnotalent/Reverse-Engineering-Tutorial)\n\n\u003cbr\u003e\n\n# IoT Pico W TLS Server\nIoT Pico W TLS Server that obtains the Pico W temperature and serves it to a TLS client where this project is designed for a MAC M series client and is based on the Raspberry Pi Foundation’s pico_examples TLS client example.\n\n\u003cbr\u003e\n\n### STEP 1: rename `wifi_creds.template` to `wifi_creds.h` and fill in your SSID and password\n\n### STEP 2: `./build.sh`\n\n### STEP 3: `./tls_client \u003cIP\u003e`\n\n### SOURCE `tls_server.c`\n```c\n/////////////////////////////////////////////////////////////////////\n// Project: Raspberry Pi Pico TLS Server Application\n// Author: Kevin Thomas\n// E-Mail: ket189@pitt.edu\n// Version: 1.0\n// Date: 02/26/25\n// Target Device: Raspberry Pi Pico W (RP2040)\n// Clock Frequency: (Depends on your board, e.g., 125 MHz)\n// Toolchain: CMake, pico-sdk, ARM-none-eabi-gcc\n// License: Apache License 2.0\n// Description: This application sets up a TLS server on port 443 \n//              using altcp_tls from lwIP, parsing an embedded \n//              self-signed certificate and private key. It sends \n//              RP2040 temperature readings once per second to \n//              connected clients and provides console logs for \n//              debugging, including connection status, sent data, \n//              and errors.\n/////////////////////////////////////////////////////////////////////\n\n #include \"pico/stdlib.h\"\n #include \"pico/cyw43_arch.h\"\n #include \"hardware/adc.h\"\n #include \"wifi_creds.h\" \n #include \u003cstdio.h\u003e\n #include \u003cstdlib.h\u003e\n #include \u003cstring.h\u003e\n \n #include \"lwip/altcp_tls.h\"\n #include \"lwip/altcp_tcp.h\"\n #include \"lwip/ip_addr.h\"\n #include \"lwip/netif.h\"\n #include \"lwip/pbuf.h\"\n \n #include \"mbedtls/x509_crt.h\"\n #include \"mbedtls/pk.h\"\n #include \"mbedtls/error.h\"\n \n #include \"cert_string.h\" \n #include \"key_string.h\"\n \n #define SERVER_PORT             443\n #define TEMP_SEND_INTERVAL_MS   1000\n \n  /**\n  * @struct TLS_SERVER_T\n  * @brief Structure that holds server state and TLS connection data.\n  * \n  * This structure is used to track the TLS server connection details and its status.\n  */\n typedef struct {\n     struct altcp_pcb *pcb;      ///\u003c lwIP control block for the connection\n     bool connected;\n     int error;\n } TLS_SERVER_T;\n \n // TLS configuration structure; holds the TLS server state\n static struct altcp_tls_config *tls_config = NULL;\n static TLS_SERVER_T *server_state = NULL;\n\n // Forward declarations\n static err_t dummy_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err);\n static void tls_server_err(void *arg, err_t err);\n static void print_server_ip(void);\n static float read_temperature(void);\n static err_t tls_server_accept(void *arg, struct altcp_pcb *newpcb, err_t err);\n static int configure_tls_cert(void);\n \n int main(void) {\n     // Initialize standard I/O for logging/debugging\n     stdio_init_all();\n\n    // Initialize CYW43 (Wi-Fi module)\n     if (cyw43_arch_init()) {\n         printf(\"❌ Failed to initialize CYW43\\n\");\n         return 1;\n     }\n     cyw43_arch_enable_sta_mode();\n \n     // Attempt to connect to the specified Wi-Fi network\n     printf(\"🔄 Connecting to Wi-Fi...\\n\");\n     if (cyw43_arch_wifi_connect_timeout_ms(\n             WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000\n         )) {\n         printf(\"❌ Failed to connect to Wi-Fi\\n\");\n         return 1;\n     }\n     printf(\"✅ Connected to Wi-Fi!\\n\");\n     print_server_ip();\n \n    // Configure TLS server\n     printf(\"🔄 Configuring TLS server...\\n\");\n     tls_config = altcp_tls_create_config_server(1);  // 1 =\u003e one cert\n     if (!tls_config) {\n         printf(\"❌ Failed to create TLS config\\n\");\n         return 1;\n     }\n \n     // Attempt to parse and add cert/key to config\n     if (configure_tls_cert() != 0) {\n         return 1; // We printed error details already\n     }\n \n     // Create altcp TLS PCB\n     struct altcp_pcb *pcb = altcp_tls_new(tls_config, IPADDR_TYPE_ANY);\n     if (!pcb) {\n         printf(\"❌ Failed to create TLS PCB\\n\");\n         return 1;\n     }\n \n     // Bind on port 443\n     err_t err = altcp_bind(pcb, IP_ADDR_ANY, SERVER_PORT);\n     if (err != ERR_OK) {\n         printf(\"❌ Failed to bind PCB, err=%d\\n\", err);\n         return 1;\n     }\n \n     // Listen for incoming TLS connections\n     pcb = altcp_listen(pcb);\n \n     // Allocate global server state\n     server_state = malloc(sizeof(TLS_SERVER_T));\n     if (!server_state) {\n         printf(\"❌ Failed to allocate server state\\n\");\n         return 1;\n     }\n     memset(server_state, 0, sizeof(TLS_SERVER_T));\n \n     // Register accept callback\n     altcp_accept(pcb, tls_server_accept);\n     altcp_arg(pcb, server_state); // Make sure the top-level listening pcb also has the arg\n     printf(\"✅ TLS server listening on port %d\\n\", SERVER_PORT);\n \n     // After a client connects, wait 500 ms, then send every second\n     const uint32_t post_connect_delay_ms = 500;\n \n     // Main loop - continuously checking for connections and sending temperature updates\n     while (1) {\n #if PICO_CYW43_ARCH_POLL\n         cyw43_arch_poll();\n #endif\n         if (server_state-\u003econnected \u0026\u0026 server_state-\u003epcb) {\n             static bool sent_first = false;\n             if (!sent_first) {\n                 sleep_ms(post_connect_delay_ms);\n                 sent_first = true;\n             }\n \n             float temp = read_temperature();\n             char msg[64];\n             snprintf(msg, sizeof(msg), \"RP2040 Temperature: %.2f C\\n\", temp);\n \n             err_t werr = altcp_write(server_state-\u003epcb, msg, strlen(msg), TCP_WRITE_FLAG_COPY);\n             if (werr == ERR_OK) {\n                 altcp_output(server_state-\u003epcb);\n                 printf(\"📡 Sent: %s\", msg);\n             } else if (werr == ERR_MEM) {\n                 altcp_output(server_state-\u003epcb);\n                 printf(\"⚠️ altcp_write returned ERR_MEM, will retry\\n\");\n             } else {\n                 printf(\"❌ altcp_write returned err=%d\\n\", werr);\n                 // Mark connection as closed\n                 server_state-\u003econnected = false;\n                 server_state-\u003epcb       = NULL;\n             }\n         } else {\n             // No valid connection\n             printf(\"⚠️ No client connected.\\n\");\n         }\n         sleep_ms(TEMP_SEND_INTERVAL_MS);\n     }\n \n     return 0; // Unreachable but good practice\n }\n\n  /**\n  * @brief Dummy receive callback that drains inbound data.\n  * \n  * @param arg Unused.\n  * @param pcb Pointer to lwIP TLS connection control block.\n  * @param p Pointer to received data buffer.\n  * @param err lwIP error code.\n  * @return ERR_OK if processed successfully.\n  */\n static err_t dummy_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) {\n    if (!p) {\n        // Client closed the connection\n        printf(\"Client closed connection (dummy_recv)\\n\");\n        return altcp_close(pcb);\n    }\n    altcp_recved(pcb, p-\u003etot_len);\n    pbuf_free(p);\n    return ERR_OK;\n}\n\n/**\n * @brief Error callback for the TLS server.\n * \n * @param arg Pointer to the server state.\n * @param err lwIP error code.\n */\nstatic void tls_server_err(void *arg, err_t err) {\n    TLS_SERVER_T *state = (TLS_SERVER_T *)arg;\n    printf(\"❌ TLS server error: %d\\n\", err);\n    if (state) {\n        state-\u003epcb = NULL;\n        state-\u003econnected = false;\n    }\n}\n\n/**\n * @brief Displays the assigned IP address of the server.\n */\nstatic void print_server_ip(void) {\n    if (netif_default \u0026\u0026 netif_is_up(netif_default)) {\n        char ip_str[16];\n        ip4addr_ntoa_r(netif_ip4_addr(netif_default), ip_str, sizeof(ip_str));\n        printf(\"✅ Server IP: %s\\n\", ip_str);\n    } else {\n        printf(\"❌ Failed to obtain IP address\\n\");\n    }\n}\n\n/**\n * @brief Reads the RP2040 internal temperature sensor.\n * \n * @return Temperature in Celsius.\n */\nstatic float read_temperature(void) {\n   static bool adc_initialized = false;\n   if (!adc_initialized) {\n       adc_init();\n       adc_set_temp_sensor_enabled(true);\n       adc_initialized = true;\n   }\n   \n   adc_select_input(4);\n   uint16_t raw = adc_read();\n   \n   // Corrected conversion formula\n   const float conversion_factor = 3.3f / (1 \u003c\u003c 12); // ADC 12-bit scale\n   float voltage = raw * conversion_factor;\n   \n   float temperature = 27.0f - (voltage - 0.706f) / 0.001721f; // Correct formula\n   return temperature;\n}\n\n/**\n * @brief Callback when a client connects to the TLS server.\n * \n * @param arg Pointer to server state.\n * @param newpcb Pointer to the new lwIP TLS control block.\n * @param err lwIP error code.\n * @return ERR_OK on success.\n */\nstatic err_t tls_server_accept(void *arg, struct altcp_pcb *newpcb, err_t err) {\n    TLS_SERVER_T *state = (TLS_SERVER_T *)arg;\n    if ((err != ERR_OK) || !newpcb) {\n        return ERR_VAL;\n    }\n    printf(\"✅ Client connected to TLS server\\n\");\n    state-\u003epcb       = newpcb;\n    state-\u003econnected = true;\n    altcp_arg(newpcb, state);\n    altcp_recv(newpcb, dummy_recv);\n    altcp_err(newpcb, tls_server_err);\n    return ERR_OK;\n}\n\n/**\n * @brief Loads the TLS certificate and private key.\n * \n * @return 0 on success, nonzero on failure.\n */\nstatic int configure_tls_cert(void) {\n    int ret;\n    char err_buf[128];\n\n    // 1. Test parse the certificate (for debug)\n    {\n        mbedtls_x509_crt manual_cert;\n        mbedtls_x509_crt_init(\u0026manual_cert);\n        ret = mbedtls_x509_crt_parse(\n            \u0026manual_cert,\n            (const unsigned char *)server_cert_pem,\n            strlen(server_cert_pem) + 1\n        );\n        if (ret != 0) {\n            mbedtls_strerror(ret, err_buf, sizeof(err_buf));\n            printf(\"❌ [Manual parse] mbedtls_x509_crt_parse failed: %d (%s)\\n\", ret, err_buf);\n            return ret;\n        }\n        printf(\"✅ [Manual parse] Certificate OK!\\n\");\n        mbedtls_x509_crt_free(\u0026manual_cert);\n    }\n\n    // 2. Parse again for altcp_tls, along with the private key\n    mbedtls_x509_crt server_cert;\n    mbedtls_pk_context server_key;\n    mbedtls_x509_crt_init(\u0026server_cert);\n    mbedtls_pk_init(\u0026server_key);\n\n    printf(\"🔍 Server Cert:\\n%s\\n\", server_cert_pem);\n    printf(\"🔍 Server Key:\\n%s\\n\", server_key_pem);\n\n    // Certificate\n    ret = mbedtls_x509_crt_parse(\u0026server_cert,\n                                 (const unsigned char *)server_cert_pem,\n                                 strlen(server_cert_pem) + 1);\n    if (ret != 0) {\n        mbedtls_strerror(ret, err_buf, sizeof(err_buf));\n        printf(\"❌ mbedtls_x509_crt_parse failed: %d (%s)\\n\", ret, err_buf);\n        return ret;\n    }\n\n    // Key\n    ret = mbedtls_pk_parse_key(\u0026server_key,\n                               (const unsigned char *)server_key_pem,\n                               strlen(server_key_pem) + 1,\n                               NULL, 0);\n    if (ret != 0) {\n        mbedtls_strerror(ret, err_buf, sizeof(err_buf));\n        printf(\"❌ mbedtls_pk_parse_key failed: %d (%s)\\n\", ret, err_buf);\n        return ret;\n    }\n\n    // 3. Add certificate and key to altcp_tls config\n    ret = altcp_tls_config_server_add_privkey_cert(\n              tls_config,\n              (const u8_t *)server_key_pem,  strlen(server_key_pem)  + 1,\n              (const u8_t *)server_cert_pem, strlen(server_cert_pem) + 1,\n              (const u8_t *)server_cert_pem, strlen(server_cert_pem) + 1\n          );\n    if (ret != ERR_OK) {\n        printf(\"❌ Failed to set server certificate, err=%d\\n\", ret);\n        return ret;\n    }\n    printf(\"✅ Server certificate successfully loaded!\\n\");\n\n    mbedtls_x509_crt_free(\u0026server_cert);\n    mbedtls_pk_free(\u0026server_key);\n\n    return 0;\n}\n```\n\n### SOURCE `tls_client.c`\n```c\n/////////////////////////////////////////////////////////////////////\n// Project: Raspberry Pi Pico TLS Client Application\n// Author: Kevin Thomas\n// E-Mail: ket189@pitt.edu\n// Version: 1.0\n// Date: 02/27/25\n// Target Device: Any Linux/macOS system (including Raspberry Pi)\n// Toolchain: GCC, OpenSSL\n// License: Apache License 2.0\n// Description: This program implements a TLS client using OpenSSL. \n//              It establishes a secure connection to a TLS server, \n//              reads incoming data, and handles connection errors. \n//              The client continuously reads messages from the server \n//              until the connection is closed. \n/////////////////////////////////////////////////////////////////////\n\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cstring.h\u003e\n#include \u003cunistd.h\u003e\n#include \u003carpa/inet.h\u003e\n#include \u003copenssl/ssl.h\u003e\n#include \u003copenssl/err.h\u003e\n\n#define SERVER_PORT 443\n\nint main(int argc, char *argv[]) {\n    // Ensure the correct number of command-line arguments are provided\n    if (argc != 2) {\n        fprintf(stderr, \"Usage: %s \u003cserver_ip\u003e\\n\", argv[0]);\n        return 1;\n    }\n\n    const char *server_ip = argv[1];\n\n    // Initialize OpenSSL library\n    SSL_library_init();\n    SSL_load_error_strings();\n    OpenSSL_add_all_algorithms();\n\n    // Create a new SSL context using TLS_client_method\n    const SSL_METHOD *method = TLS_client_method();\n    if (!method) {\n        fprintf(stderr, \"Unable to create TLS method\\n\");\n        ERR_print_errors_fp(stderr);\n        return 1;\n    }\n    SSL_CTX *ctx = SSL_CTX_new(method);\n    if (!ctx) {\n        ERR_print_errors_fp(stderr);\n        return 1;\n    }\n\n    // Optionally ignore self-signed certificate errors:\n    // SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);\n\n    // Create a new SSL connection state object\n    SSL *ssl = SSL_new(ctx);\n    if (!ssl) {\n        ERR_print_errors_fp(stderr);\n        SSL_CTX_free(ctx);\n        return 1;\n    }\n\n    // Create a TCP socket\n    int sockfd = socket(AF_INET, SOCK_STREAM, 0);\n    if (sockfd \u003c 0) {\n        perror(\"socket\");\n        SSL_free(ssl);\n        SSL_CTX_free(ctx);\n        return 1;\n    }\n\n    // Setup server address\n    struct sockaddr_in server_addr;\n    memset(\u0026server_addr, 0, sizeof(server_addr));\n    server_addr.sin_family = AF_INET;\n    server_addr.sin_port = htons(SERVER_PORT);\n    if (inet_pton(AF_INET, server_ip, \u0026server_addr.sin_addr) \u003c= 0) {\n        perror(\"inet_pton\");\n        close(sockfd);\n        SSL_free(ssl);\n        SSL_CTX_free(ctx);\n        return 1;\n    }\n\n    // Connect to the server\n    if (connect(sockfd, (struct sockaddr *)\u0026server_addr, sizeof(server_addr)) \u003c 0) {\n        perror(\"connect\");\n        close(sockfd);\n        SSL_free(ssl);\n        SSL_CTX_free(ctx);\n        return 1;\n    }\n\n    // Attach the socket to the SSL object\n    SSL_set_fd(ssl, sockfd);\n\n    // Perform the TLS handshake\n    if (SSL_connect(ssl) \u003c= 0) {\n        ERR_print_errors_fp(stderr);\n        close(sockfd);\n        SSL_free(ssl);\n        SSL_CTX_free(ctx);\n        return 1;\n    }\n\n    printf(\"Connected to %s via TLS %s\\n\", server_ip, SSL_get_version(ssl));\n\n    // Read lines from the server until it closes\n    char buf[1024];\n    while (1) {\n        int bytes = SSL_read(ssl, buf, sizeof(buf) - 1);\n        if (bytes \u003e 0) {\n            buf[bytes] = '\\0';\n            printf(\"%s\", buf);\n            fflush(stdout);\n        } else if (bytes == 0) {\n            // Server closed connection gracefully\n            printf(\"\\nServer closed connection.\\n\");\n            break;\n        } else {\n            // Error or shutdown\n            ERR_print_errors_fp(stderr);\n            break;\n        }\n    }\n\n    // Clean up\n    SSL_shutdown(ssl);\n    close(sockfd);\n    SSL_free(ssl);\n    SSL_CTX_free(ctx);\n\n    return 0;\n}\n```\n\n\u003cbr\u003e\n\n# License\n[Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmytechnotalent%2Fipts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmytechnotalent%2Fipts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmytechnotalent%2Fipts/lists"}