diff --git a/examples/openssl_server/Makefile b/examples/openssl_server/Makefile new file mode 100644 index 00000000..52bb4b7e --- /dev/null +++ b/examples/openssl_server/Makefile @@ -0,0 +1,121 @@ +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of object file images to be generated () +# GEN_BINS - list of binaries to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +TARGET = eagle +#FLAVOR = release +FLAVOR = debug + +#EXTRA_CCFLAGS += -u + +ifndef PDIR # { +GEN_IMAGES= eagle.app.v6.out +GEN_BINS= eagle.app.v6.bin +SPECIAL_MKTARGETS=$(APP_MKTARGETS) +SUBDIRS= \ + user + +endif # } PDIR + +LDDIR = $(SDK_PATH)/ld + +CCFLAGS += -Os + +TARGET_LDFLAGS = \ + -nostdlib \ + -Wl,-EL \ + --longcalls \ + --text-section-literals + +ifeq ($(FLAVOR),debug) + TARGET_LDFLAGS += -g -O2 +endif + +ifeq ($(FLAVOR),release) + TARGET_LDFLAGS += -g -O0 +endif + +COMPONENTS_eagle.app.v6 = \ + user/libuser.a + +LINKFLAGS_eagle.app.v6 = \ + -L$(SDK_PATH)/lib \ + -Wl,--gc-sections \ + -nostdlib \ + -T$(LD_FILE) \ + -Wl,--no-check-sections \ + -u call_user_start \ + -Wl,-static \ + -Wl,--start-group \ + -lcirom \ + -lgcc \ + -lhal \ + -lcrypto \ + -lfreertos \ + -llwip \ + -lmain \ + -lnet80211 \ + -lphy \ + -lpp \ + -lmbedtls \ + -lopenssl \ + -lwpa \ + $(DEP_LIBS_eagle.app.v6)\ + -Wl,--end-group + +DEPENDS_eagle.app.v6 = \ + $(LD_FILE) \ + $(LDDIR)/eagle.rom.addr.v6.ld + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# + +#UNIVERSAL_TARGET_DEFINES = \ + +# Other potential configuration flags include: +# -DTXRX_TXBUF_DEBUG +# -DTXRX_RXBUF_DEBUG +# -DWLAN_CONFIG_CCX +CONFIGURATION_DEFINES = -DICACHE_FLASH + +DEFINES += \ + $(UNIVERSAL_TARGET_DEFINES) \ + $(CONFIGURATION_DEFINES) + +DDEFINES += \ + $(UNIVERSAL_TARGET_DEFINES) \ + $(CONFIGURATION_DEFINES) + + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include -I include -I $(SDK_PATH)/include/openssl +sinclude $(SDK_PATH)/Makefile + +.PHONY: FORCE +FORCE: + diff --git a/examples/openssl_server/README.md b/examples/openssl_server/README.md new file mode 100644 index 00000000..0afaab48 --- /dev/null +++ b/examples/openssl_server/README.md @@ -0,0 +1,44 @@ +1. Run ./gencrt.sh or if you have your own certificate, move to the openssl_server directory, the name is ca.crt,server.crt, server.key, client.crt and client.key. + + The server.crt and client.crt was generate by the same ca.crt in ./gencrt.sh. + + Server side needs ca.crt(to verify client.crt), server.crt, server.key + + Client side needs ca.crt(to verify server.crt), client.crt, client.key + + If you have two ca.crt to generate server.crt and client.crt respectively, client1.crt is generate by ca1.crt and client1.key, server2.crt is generate by ca2.crt and server2.key: + + Client side needs ca2.crt, client1.crt, client1.key. + + Server side needs ca1.crt, server2.crt, server2.key. + + Rename ca1.crt server2.crt server2.key to ca.crt server.crt server.key and run ./genheader.sh. + + Use ca2.crt in openssl s_client -CAfile option. + +2. Run ./genheader.sh. + +3. Modify thease two lines in file user_config.h to your local Wi-Fi SSID and Password. + + ```#define SSID "HUAWEI001"``` + + ```#define PASSWORD ""``` + +4. Make sure that the computer and ESP8266 are in the same local area network. + +5. Run ./gen_misc.sh. + +6. Download bin file to ESP8266. + + Find server ip address in ESP8266 UART log: ip:192.168.3.6,mask:255.255.255.0,gw:192.168.3.1. + +7. Run openssl s_client -CAfile ca.crt -cert client.crt -key client.key -verify 1 -tls1_1 -host 192.168.3.6 -port 443. + + +**ATTENTION** + +**1. Make sure the free heap size larger than 30K.** + +**2. Make sure the private key length larger than 2048.** + +**3. Make sure the fragment size range is between 2048 and 8192.** diff --git a/examples/openssl_server/gen_misc.sh b/examples/openssl_server/gen_misc.sh new file mode 100755 index 00000000..11bd9d0c --- /dev/null +++ b/examples/openssl_server/gen_misc.sh @@ -0,0 +1,191 @@ +#!/bin/bash + +:< ssl_server_crt.h + +# set server crt for use in the server +xxd -i server.crt | sed -e "s/server_crt/server_crt/" >> ssl_server_crt.h + +# set private key for use in the server +xxd -i server.key | sed -e "s/server_key/server_key/" >> ssl_server_crt.h + +mv ssl_server_crt.h ./include diff --git a/examples/openssl_server/include/openssl_demo.h b/examples/openssl_server/include/openssl_demo.h new file mode 100644 index 00000000..fa94209d --- /dev/null +++ b/examples/openssl_server/include/openssl_demo.h @@ -0,0 +1,30 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2017 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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. + * + */ + +#ifndef _OPENSSL_DEMO_H_ +#define _OPENSSL_DEMO_H_ + +void user_conn_init(void); + +#endif diff --git a/examples/openssl_server/include/user_config.h b/examples/openssl_server/include/user_config.h new file mode 100644 index 00000000..4e337b0f --- /dev/null +++ b/examples/openssl_server/include/user_config.h @@ -0,0 +1,34 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2017 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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. + * + */ + +#ifndef __USER_CONFIG_H__ +#define __USER_CONFIG_H__ + +#include "openssl_demo.h" + +#define SSID "HUAWEI001" +#define PASSWORD "" + +#endif + diff --git a/examples/openssl_server/user/Makefile b/examples/openssl_server/user/Makefile new file mode 100644 index 00000000..dd3837c7 --- /dev/null +++ b/examples/openssl_server/user/Makefile @@ -0,0 +1,44 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = libuser.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/examples/openssl_server/user/openssl_demo.c b/examples/openssl_server/user/openssl_demo.c new file mode 100644 index 00000000..48c21586 --- /dev/null +++ b/examples/openssl_server/user/openssl_demo.c @@ -0,0 +1,241 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2017 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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. + * + */ + +#include +#include "openssl_demo.h" +#include "openssl/ssl.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "espressif/c_types.h" +#include "espressif/esp_misc.h" +#include "lwip/sockets.h" +#include "ssl_server_crt.h" + +#define OPENSSL_DEMO_THREAD_NAME "ssl_demo" +#define OPENSSL_DEMO_THREAD_STACK_WORDS 2048 +#define OPENSSL_DEMO_THREAD_PRORIOTY 6 + +/* +Fragment size range 2048~8192 +| Private key len | Fragment size recommend | +| RSA2048 | 2048 | +| RSA3072 | 3072 | +| RSA4096 | 4096 | +*/ +#define OPENSSL_DEMO_FRAGMENT_SIZE 2048 + +/* Local server tcp port */ +#define OPENSSL_DEMO_LOCAL_TCP_PORT 443 + +#define OPENSSL_DEMO_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" + +/* receive length */ +#define OPENSSL_DEMO_RECV_BUF_LEN 1024 + +LOCAL xTaskHandle openssl_handle; + +LOCAL char send_data[] = OPENSSL_DEMO_REQUEST; +LOCAL int send_bytes = sizeof(send_data); + +LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + +LOCAL void openssl_demo_thread(void* p) +{ + int ret; + + SSL_CTX* ctx; + SSL* ssl; + + struct sockaddr_in sock_addr; + int sockfd, new_sockfd; + int recv_bytes = 0; + socklen_t addr_len; + + printf("OpenSSL demo thread start...\n"); + + printf("create SSL context ......"); + ctx = SSL_CTX_new(TLSv1_1_server_method()); + + if (!ctx) { + printf("failed\n"); + goto failed1; + } + + printf("OK\n"); + + printf("load ca crt ......"); + X509* cacrt = d2i_X509(NULL, ca_crt, ca_crt_len); + + if (cacrt) { + SSL_CTX_add_client_CA(ctx, cacrt); + printf("OK\n"); + } else { + printf("failed\n"); + goto failed2; + } + + printf("load server crt ......"); + ret = SSL_CTX_use_certificate_ASN1(ctx, server_crt_len, server_crt); + + if (ret) { + printf("OK\n"); + } else { + printf("failed\n"); + goto failed2; + } + + printf("load server private key ......"); + ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, server_key, server_key_len); + + if (ret) { + printf("OK\n"); + } else { + printf("failed\n"); + goto failed2; + } + + printf("set verify mode verify peer\n"); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + + printf("set SSL context read buffer size ......OK\n"); + SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); + + printf("create socket ......"); + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) { + printf("failed\n"); + goto failed2; + } + + printf("OK\n"); + + printf("socket bind ......"); + 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_DEMO_LOCAL_TCP_PORT); + + ret = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + + if (ret) { + printf("bind failed\n"); + goto failed3; + } + + printf("bind OK\n"); + + printf("server socket listen ......"); + ret = listen(sockfd, 32); + + if (ret) { + printf("failed\n"); + goto failed3; + } + + printf("OK\n"); + +reconnect: + printf("SSL server create ......"); + ssl = SSL_new(ctx); + + if (!ssl) { + printf("failed\n"); + goto failed3; + } + + printf("OK\n"); + + printf("SSL server socket accept client ......"); + new_sockfd = accept(sockfd, (struct sockaddr*)&sock_addr, &addr_len); + + if (new_sockfd < 0) { + printf("failed"); + goto failed4; + } + + printf("OK\n"); + + SSL_set_fd(ssl, new_sockfd); + + printf("SSL server accept client ......"); + ret = SSL_accept(ssl); + + if (!ret) { + printf("failed\n"); + goto failed5; + } + + printf("OK\n"); + + do { + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + + if (ret <= 0) { + break; + } + + recv_bytes += ret; + recv_buf[ret] = '\0'; + printf("%s", recv_buf); + } while (1); + + SSL_shutdown(ssl); +failed5: + close(new_sockfd); + new_sockfd = -1; +failed4: + SSL_free(ssl); + ssl = NULL; + goto reconnect; +failed3: + close(sockfd); + sockfd = -1; +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + printf("task exit\n"); + + return ; +} + +void user_conn_init(void) +{ + int ret; + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); + + if (ret != pdPASS) { + printf("create thread %s failed\n", OPENSSL_DEMO_THREAD_NAME); + return ; + } +} + diff --git a/examples/openssl_server/user/user_main.c b/examples/openssl_server/user/user_main.c new file mode 100644 index 00000000..28270319 --- /dev/null +++ b/examples/openssl_server/user/user_main.c @@ -0,0 +1,116 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2017 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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. + * + */ + + +#include "esp_common.h" +#include "user_config.h" + +/****************************************************************************** + * FunctionName : user_rf_cal_sector_set + * Description : SDK just reversed 4 sectors, used for rf init data and paramters. + * We add this function to force users to set rf cal sector, since + * we don't know which sector is free in user's application. + * sector map for last several sectors : ABCCC + * A : rf cal + * B : rf init data + * C : sdk parameters + * Parameters : none + * Returns : rf cal sector +*******************************************************************************/ +uint32 user_rf_cal_sector_set(void) +{ + flash_size_map size_map = system_get_flash_size_map(); + uint32 rf_cal_sec = 0; + + switch (size_map) { + case FLASH_SIZE_4M_MAP_256_256: + rf_cal_sec = 128 - 5; + break; + + case FLASH_SIZE_8M_MAP_512_512: + rf_cal_sec = 256 - 5; + break; + + case FLASH_SIZE_16M_MAP_512_512: + case FLASH_SIZE_16M_MAP_1024_1024: + rf_cal_sec = 512 - 5; + break; + + case FLASH_SIZE_32M_MAP_512_512: + case FLASH_SIZE_32M_MAP_1024_1024: + rf_cal_sec = 1024 - 5; + break; + + case FLASH_SIZE_64M_MAP_1024_1024: + rf_cal_sec = 2048 - 5; + break; + + case FLASH_SIZE_128M_MAP_1024_1024: + rf_cal_sec = 4096 - 5; + break; + + default: + rf_cal_sec = 0; + break; + } + + return rf_cal_sec; +} + +void wifi_event_handler_cb(System_Event_t* event) +{ + if (event == NULL) { + return; + } + + switch (event->event_id) { + case EVENT_STAMODE_GOT_IP: + printf("sta got ip , creat task %d\n", system_get_free_heap_size()); + user_conn_init(); + break; + + default: + break; + } +} + +/****************************************************************************** + * FunctionName : user_init + * Description : entry of user application, init user function here + * Parameters : none + * Returns : none +*******************************************************************************/ +void user_init(void) +{ + printf("SDK version:%s %d\n", system_get_sdk_version(), system_get_free_heap_size()); + wifi_set_opmode(STATION_MODE); + + // set AP parameter + struct station_config config; + bzero(&config, sizeof(struct station_config)); + sprintf(config.ssid, SSID); + sprintf(config.password, PASSWORD); + wifi_station_set_config(&config); + wifi_set_event_handler_cb(wifi_event_handler_cb); +}