examples: Add esp-ssl example tests server/client
Closes IDF-1156
This commit is contained in:
committed by
Suren Gabrielyan
parent
822cdd81ef
commit
823abfdfd5
@@ -1,15 +1,27 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config TARGET_DOMAIN
|
||||
choice EXAMPLE_OPENSSL_CLIENT_URI_SOURCE
|
||||
prompt "SSL Client URI source"
|
||||
default EXAMPLE_OPENSSL_CLIENT_URI_FROM_STRING
|
||||
help
|
||||
Selects the source of the URI used in the example.
|
||||
|
||||
config EXAMPLE_OPENSSL_CLIENT_URI_FROM_STRING
|
||||
bool "From string"
|
||||
|
||||
config EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN
|
||||
bool "From stdin"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_OPENSSL_CLIENT_TARGET_DOMAIN
|
||||
string "Target Domain"
|
||||
default "www.baidu.com"
|
||||
help
|
||||
Target domain for the example to connect to.
|
||||
|
||||
config TARGET_PORT_NUMBER
|
||||
int "Target port number"
|
||||
range 0 65535
|
||||
default 443
|
||||
config EXAMPLE_OPENSSL_CLIENT_TARGET_PORT
|
||||
string "Target port number"
|
||||
default "443"
|
||||
help
|
||||
Target port number for the example to connect to.
|
||||
|
||||
|
||||
26
examples/protocols/openssl_client/main/baidu_ca.crt
Normal file
26
examples/protocols/openssl_client/main/baidu_ca.crt
Normal file
@@ -0,0 +1,26 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEaTCCA1GgAwIBAgILBAAAAAABRE7wQkcwDQYJKoZIhvcNAQELBQAwVzELMAkG
|
||||
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
|
||||
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNDAyMjAxMDAw
|
||||
MDBaFw0yNDAyMjAxMDAwMDBaMGYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
|
||||
YWxTaWduIG52LXNhMTwwOgYDVQQDEzNHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBW
|
||||
YWxpZGF0aW9uIENBIC0gU0hBMjU2IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||
DwAwggEKAoIBAQDHDmw/I5N/zHClnSDDDlM/fsBOwphJykfVI+8DNIV0yKMCLkZc
|
||||
C33JiJ1Pi/D4nGyMVTXbv/Kz6vvjVudKRtkTIso21ZvBqOOWQ5PyDLzm+ebomchj
|
||||
SHh/VzZpGhkdWtHUfcKc1H/hgBKueuqI6lfYygoKOhJJomIZeg0k9zfrtHOSewUj
|
||||
mxK1zusp36QUArkBpdSmnENkiN74fv7j9R7l/tyjqORmMdlMJekYuYlZCa7pnRxt
|
||||
Nw9KHjUgKOKv1CGLAcRFrW4rY6uSa2EKTSDtc7p8zv4WtdufgPDWi2zZCHlKT3hl
|
||||
2pK8vjX5s8T5J4BO/5ZS5gIg4Qdz6V0rvbLxAgMBAAGjggElMIIBITAOBgNVHQ8B
|
||||
Af8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUlt5h8b0cFilT
|
||||
HMDMfTuDAEDmGnwwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0
|
||||
dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMDMGA1UdHwQsMCow
|
||||
KKAmoCSGImh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5uZXQvcm9vdC5jcmwwPQYIKwYB
|
||||
BQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNv
|
||||
bS9yb290cjEwHwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZI
|
||||
hvcNAQELBQADggEBAEYq7l69rgFgNzERhnF0tkZJyBAW/i9iIxerH4f4gu3K3w4s
|
||||
32R1juUYcqeMOovJrKV3UPfvnqTgoI8UV6MqX+x+bRDmuo2wCId2Dkyy2VG7EQLy
|
||||
XN0cvfNVlg/UBsD84iOKJHDTu/B5GqdhcIOKrwbFINihY9Bsrk8y1658GEV1BSl3
|
||||
30JAZGSGvip2CTFvHST0mdCF/vIhCPnG9vHQWe3WVjwIKANnuvD58ZAWR65n5ryA
|
||||
SOlCdjSXVWkkDoPWoC209fN5ikkodBpBocLTJIg1MGCUF7ThBCIxPTsvFwayuJ2G
|
||||
K1pp74P1S8SqtCr4fKGxhZSM9AyHDPSsQPhZSZg=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,3 +1,10 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
|
||||
ifdef CONFIG_EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN
|
||||
COMPONENT_EMBED_TXTFILES := ${PROJECT_PATH}/server_certs/ca.crt
|
||||
else
|
||||
COMPONENT_EMBED_TXTFILES := ${PROJECT_PATH}/main/baidu_ca.crt
|
||||
endif
|
||||
COMPONENT_EMBED_TXTFILES += ${PROJECT_PATH}/server_certs/ca.key
|
||||
|
||||
@@ -17,17 +17,15 @@
|
||||
the config you want - ie #define OPENSSL_EXAMPLE_TARGET_NAME "www.baidu.com"
|
||||
and ie #define OPENSSL_EXAMPLE_TARGET_TCP_PORT 433
|
||||
*/
|
||||
#define OPENSSL_EXAMPLE_TARGET_NAME CONFIG_TARGET_DOMAIN
|
||||
#define OPENSSL_EXAMPLE_TARGET_TCP_PORT CONFIG_TARGET_PORT_NUMBER
|
||||
#define EXAMPLE_OPENSSL_TARGET_DOMAIN CONFIG_EXAMPLE_OPENSSL_CLIENT_TARGET_DOMAIN
|
||||
#define EXAMPLE_OPENSSL_TARGET_PORT CONFIG_EXAMPLE_OPENSSL_CLIENT_TARGET_PORT
|
||||
|
||||
#define OPENSSL_EXAMPLE_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n"
|
||||
#define EXAMPLE_OPENSSL_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n"
|
||||
|
||||
#define OPENSSL_EXAMPLE_TASK_NAME "openssl_example"
|
||||
#define OPENSSL_EXAMPLE_TASK_STACK_WORDS 10240
|
||||
#define OPENSSL_EXAMPLE_TASK_PRIORITY 8
|
||||
#define EXAMPLE_OPENSSL_TASK_NAME "openssl_example"
|
||||
#define EXAMPLE_OPENSSL_TASK_STACK_WORDS 10240
|
||||
#define EXAMPLE_OPENSSL_TASK_PRIORITY 8
|
||||
|
||||
#define OPENSSL_EXAMPLE_RECV_BUF_LEN 1024
|
||||
|
||||
#define OPENSSL_EXAMPLE_LOCAL_TCP_PORT 443
|
||||
#define EXAMPLE_OPENSSL_RECV_BUF_LEN 1024
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* OpenSSL client Example
|
||||
/* OpenSSL Client Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
@@ -6,172 +6,151 @@
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "openssl_client_example.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "protocol_examples_common.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
const static char *TAG = "openssl_example";
|
||||
static const char *TAG = "openssl_example";
|
||||
|
||||
static void openssl_example_task(void *p)
|
||||
static int open_connection(const char *host, char *port)
|
||||
{
|
||||
int ret;
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
struct addrinfo * res;
|
||||
struct in_addr *addr;
|
||||
int sd;
|
||||
int err = getaddrinfo(host, port, &hints, &res);
|
||||
if (err < 0) {
|
||||
ESP_LOGE(TAG, "getaddrinfo() failed for IPV4 destination address. error: %d", err);
|
||||
return -1;
|
||||
}
|
||||
if (res == 0) {
|
||||
ESP_LOGE(TAG, "getaddrinfo() did not return any addresses");
|
||||
return -1;
|
||||
}
|
||||
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
|
||||
ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));
|
||||
sd = socket(res->ai_family, res->ai_socktype, 0);
|
||||
if(sd < 0) {
|
||||
ESP_LOGE(TAG, "Failed to allocate socket.");
|
||||
freeaddrinfo(res);
|
||||
return -1;
|
||||
}
|
||||
if (connect(sd, res->ai_addr, res->ai_addrlen) != 0) {
|
||||
ESP_LOGE(TAG, "Socket connect failed");
|
||||
return -1;
|
||||
}
|
||||
return sd;
|
||||
}
|
||||
|
||||
static SSL_CTX* init_contex(void)
|
||||
{
|
||||
|
||||
#if CONFIG_EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN
|
||||
extern const unsigned char cacert_pem_start[] asm("_binary_ca_crt_start");
|
||||
extern const unsigned char cacert_pem_end[] asm("_binary_ca_crt_end");
|
||||
#else
|
||||
extern const unsigned char cacert_pem_start[] asm("_binary_baidu_ca_crt_start");
|
||||
extern const unsigned char cacert_pem_end[] asm("_binary_baidu_ca_crt_end");
|
||||
#endif
|
||||
const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start;
|
||||
|
||||
const SSL_METHOD *mtd = TLSv1_1_client_method();
|
||||
SSL_CTX *ctx = SSL_CTX_new(mtd); /* Create new context */
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
|
||||
X509 *x = d2i_X509(NULL, cacert_pem_start, cacert_pem_bytes);
|
||||
if(!x) {
|
||||
ESP_LOGI(TAG,"Loading certs failed \n");
|
||||
}
|
||||
SSL_CTX_add_client_CA(ctx, x);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void start_example(const char *host, char *port)
|
||||
{
|
||||
SSL_CTX *ctx = NULL;
|
||||
SSL *ssl = NULL;
|
||||
int sockfd;
|
||||
struct sockaddr_in sock_addr;
|
||||
struct hostent *hp;
|
||||
struct ip4_addr *ip4_addr;
|
||||
int ret;
|
||||
|
||||
int recv_bytes = 0;
|
||||
char recv_buf[OPENSSL_EXAMPLE_RECV_BUF_LEN];
|
||||
|
||||
const char send_data[] = OPENSSL_EXAMPLE_REQUEST;
|
||||
const int send_bytes = sizeof(send_data);
|
||||
|
||||
ESP_LOGI(TAG, "OpenSSL demo thread start OK");
|
||||
|
||||
ESP_LOGI(TAG, "get target IP address");
|
||||
hp = gethostbyname(OPENSSL_EXAMPLE_TARGET_NAME);
|
||||
if (!hp) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
goto failed1;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
ip4_addr = (struct ip4_addr *)hp->h_addr;
|
||||
ESP_LOGI(TAG, IPSTR, IP2STR(ip4_addr));
|
||||
|
||||
ESP_LOGI(TAG, "create SSL context ......");
|
||||
ctx = SSL_CTX_new(TLSv1_1_client_method());
|
||||
ctx = init_contex();
|
||||
if (!ctx) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
ESP_LOGE(TAG, "Failed");
|
||||
goto failed1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Trying connect to %s port %s ...", host, port);
|
||||
sockfd = open_connection(host, port);
|
||||
if(sockfd < 0) {
|
||||
ESP_LOGE(TAG,"Failed");
|
||||
goto failed1;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
ESP_LOGI(TAG, "create socket ......");
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
ESP_LOGI(TAG, "Create SSL obj");
|
||||
ssl = SSL_new(ctx);
|
||||
if (!ssl) {
|
||||
ESP_LOGE(TAG,"Failed");
|
||||
goto failed2;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
ESP_LOGI(TAG, "bind socket ......");
|
||||
memset(&sock_addr, 0, sizeof(sock_addr));
|
||||
sock_addr.sin_family = AF_INET;
|
||||
sock_addr.sin_addr.s_addr = 0;
|
||||
sock_addr.sin_port = htons(OPENSSL_EXAMPLE_LOCAL_TCP_PORT);
|
||||
ret = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
|
||||
if (ret) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
goto failed3;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
ESP_LOGI(TAG, "socket connect to remote %s ......", OPENSSL_EXAMPLE_TARGET_NAME);
|
||||
memset(&sock_addr, 0, sizeof(sock_addr));
|
||||
sock_addr.sin_family = AF_INET;
|
||||
sock_addr.sin_addr.s_addr = ip4_addr->addr;
|
||||
sock_addr.sin_port = htons(OPENSSL_EXAMPLE_TARGET_TCP_PORT);
|
||||
ret = connect(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
|
||||
if (ret) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
goto failed3;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
ESP_LOGI(TAG, "create SSL ......");
|
||||
ssl = SSL_new(ctx);
|
||||
if (!ssl) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
goto failed3;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
SSL_set_fd(ssl, sockfd);
|
||||
|
||||
ESP_LOGI(TAG, "SSL connected to %s port %d ......",
|
||||
OPENSSL_EXAMPLE_TARGET_NAME, OPENSSL_EXAMPLE_TARGET_TCP_PORT);
|
||||
ret = SSL_connect(ssl);
|
||||
if (!ret) {
|
||||
ESP_LOGI(TAG, "failed " );
|
||||
goto failed4;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
ESP_LOGI(TAG, "send https request to %s port %d ......",
|
||||
OPENSSL_EXAMPLE_TARGET_NAME, OPENSSL_EXAMPLE_TARGET_TCP_PORT);
|
||||
ret = SSL_write(ssl, send_data, send_bytes);
|
||||
if (ret <= 0) {
|
||||
ESP_LOGI(TAG, "failed");
|
||||
goto failed5;
|
||||
ESP_LOGE(TAG,"SSL Connection Failed");
|
||||
goto failed3;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
|
||||
do {
|
||||
ret = SSL_read(ssl, recv_buf, OPENSSL_EXAMPLE_RECV_BUF_LEN - 1);
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
recv_buf[ret] = '\0';
|
||||
recv_bytes += ret;
|
||||
ESP_LOGI(TAG, "%s", recv_buf);
|
||||
} while (1);
|
||||
|
||||
ESP_LOGI(TAG, "totally read %d bytes data from %s ......", recv_bytes, OPENSSL_EXAMPLE_TARGET_NAME);
|
||||
|
||||
failed5:
|
||||
SSL_shutdown(ssl);
|
||||
failed4:
|
||||
ESP_LOGI(TAG,"SSL Connection Succeed");
|
||||
failed3:
|
||||
SSL_free(ssl);
|
||||
ssl = NULL;
|
||||
failed3:
|
||||
failed2:
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
failed2:
|
||||
failed1:
|
||||
SSL_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
failed1:
|
||||
vTaskDelete(NULL);
|
||||
return ;
|
||||
}
|
||||
|
||||
static void openssl_example_client_init(void)
|
||||
#if CONFIG_EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN
|
||||
static void get_string(char *line, size_t size)
|
||||
{
|
||||
int ret;
|
||||
xTaskHandle openssl_handle;
|
||||
|
||||
ret = xTaskCreate(openssl_example_task,
|
||||
OPENSSL_EXAMPLE_TASK_NAME,
|
||||
OPENSSL_EXAMPLE_TASK_STACK_WORDS,
|
||||
NULL,
|
||||
OPENSSL_EXAMPLE_TASK_PRIORITY,
|
||||
&openssl_handle);
|
||||
|
||||
if (ret != pdPASS) {
|
||||
ESP_LOGI(TAG, "create thread %s failed", OPENSSL_EXAMPLE_TASK_NAME);
|
||||
int count = 0;
|
||||
while (count < size) {
|
||||
int c = fgetc(stdin);
|
||||
if (c == '\n') {
|
||||
line[count] = '\0';
|
||||
break;
|
||||
} else if (c > 0 && c < 127) {
|
||||
line[count] = c;
|
||||
++count;
|
||||
}
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN */
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
char host[128] = EXAMPLE_OPENSSL_TARGET_DOMAIN;
|
||||
char port[32] = EXAMPLE_OPENSSL_TARGET_PORT;
|
||||
|
||||
ESP_LOGI(TAG, "[APP] Startup..");
|
||||
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
|
||||
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
|
||||
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
@@ -182,5 +161,10 @@ void app_main(void)
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
openssl_example_client_init();
|
||||
#if CONFIG_EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN
|
||||
char line[256] = "";
|
||||
get_string(line, sizeof(line));
|
||||
sscanf(line, "%s %s", host, port);
|
||||
#endif /* CONFIG_EXAMPLE_OPENSSL_CLIENT_URI_FROM_STDIN */
|
||||
start_example(host, port);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user