/* HTTPS GET Example using plain mbedTLS sockets * * Contacts the howsmyssl.com API via TLS v1.2 and reads a JSON * response. * * Adapted from the ssl_client1 example in mbedtls. * * SPDX-FileCopyrightText: 2006-2016 ARM Limited, All Rights Reserved * * SPDX-License-Identifier: Apache-2.0 * * SPDX-FileContributor: 2015-2022 Espressif Systems (Shanghai) CO LTD */ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_wifi.h" #include "esp_event.h" #include "esp_log.h" #include "esp_system.h" #include "nvs_flash.h" #include "protocol_examples_common.h" #include "esp_netif.h" #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include "lwip/netdb.h" #include "lwip/dns.h" #include "esp_tls.h" #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE #include "esp_crt_bundle.h" #endif /* Constants that aren't configurable in menuconfig */ #define WEB_SERVER "www.howsmyssl.com" #define WEB_PORT "443" #define WEB_URL "https://www.howsmyssl.com/a/check" static const char *TAG = "example"; static const char REQUEST[] = "GET " WEB_URL " HTTP/1.1\r\n" "Host: "WEB_SERVER"\r\n" "User-Agent: esp-idf/1.0 esp32\r\n" "\r\n"; /* Root cert for howsmyssl.com, taken from server_root_cert.pem The PEM file was extracted from the output of this command: openssl s_client -showcerts -connect www.howsmyssl.com:443 = 0) { ESP_LOGI(TAG, "%d bytes written", ret); written_bytes += ret; } else if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "esp_tls_conn_write returned: [0x%02X](%s)", ret, esp_err_to_name(ret)); goto exit; } } while (written_bytes < sizeof(REQUEST)); ESP_LOGI(TAG, "Reading HTTP response..."); do { len = sizeof(buf) - 1; bzero(buf, sizeof(buf)); ret = esp_tls_conn_read(tls, (char *)buf, len); if (ret == ESP_TLS_ERR_SSL_WANT_WRITE || ret == ESP_TLS_ERR_SSL_WANT_READ) { continue; } if (ret < 0) { ESP_LOGE(TAG, "esp_tls_conn_read returned [-0x%02X](%s)", -ret, esp_err_to_name(ret)); break; } if (ret == 0) { ESP_LOGI(TAG, "connection closed"); break; } len = ret; ESP_LOGD(TAG, "%d bytes read", len); /* Print response directly to stdout as it is read */ for (int i = 0; i < len; i++) { putchar(buf[i]); } putchar('\n'); // JSON output doesn't have a newline at end } while (1); exit: esp_tls_conn_delete(tls); for (int countdown = 10; countdown >= 0; countdown--) { ESP_LOGI(TAG, "%d...", countdown); vTaskDelay(1000 / portTICK_PERIOD_MS); } } #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE static void https_get_request_using_crt_bundle(void) { ESP_LOGI(TAG, "https_request using crt bundle"); esp_tls_cfg_t cfg = { .crt_bundle_attach = esp_crt_bundle_attach, }; https_get_request(cfg); } #endif // CONFIG_MBEDTLS_CERTIFICATE_BUNDLE static void https_get_request_using_cacert_buf(void) { ESP_LOGI(TAG, "https_request using cacert_buf"); esp_tls_cfg_t cfg = { .cacert_buf = (const unsigned char *) server_root_cert_pem_start, .cacert_bytes = server_root_cert_pem_end - server_root_cert_pem_start, }; https_get_request(cfg); } static void https_get_request_using_global_ca_store(void) { esp_err_t esp_ret = ESP_FAIL; ESP_LOGI(TAG, "https_request using global ca_store"); esp_ret = esp_tls_set_global_ca_store(server_root_cert_pem_start, server_root_cert_pem_end - server_root_cert_pem_start); if (esp_ret != ESP_OK) { ESP_LOGE(TAG, "Error in setting the global ca store: [%02X] (%s),could not complete the https_request using global_ca_store", esp_ret, esp_err_to_name(esp_ret)); return; } esp_tls_cfg_t cfg = { .use_global_ca_store = true, }; https_get_request(cfg); esp_tls_free_global_ca_store(); } static void https_request_task(void *pvparameters) { ESP_LOGI(TAG, "Start https_request example"); #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE https_get_request_using_crt_bundle(); #endif https_get_request_using_cacert_buf(); https_get_request_using_global_ca_store(); ESP_LOGI(TAG, "Finish https_request example"); vTaskDelete(NULL); } void app_main(void) { ESP_ERROR_CHECK( nvs_flash_init() ); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. * Read "Establishing Wi-Fi or Ethernet Connection" section in * examples/protocols/README.md for more information about this function. */ ESP_ERROR_CHECK(example_connect()); xTaskCreate(&https_request_task, "https_get_task", 8192, NULL, 5, NULL); }