feature/openssl: add the openssl server demo

This commit is contained in:
Dong Heng 2016-11-15 15:08:51 +08:00
parent dfaac25a37
commit a2b1f4221b
8 changed files with 383 additions and 0 deletions

View file

@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := openssl_server
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,20 @@
# Openssl Example
The Example contains of OpenSSL server demo.
First you should configure the project by "make menuconfig":
Example Configuration ->
1. WiFi SSID: you own wifi that you pc is connected to alse.
1. WiFi Password: wifi password
IF you want to test the OpenSSL server demo:
1. compile the code and load the firmware
2. input the context of "https://192.168.17.128" into your web browser, the IP of your module may not be 192.168.17.128, you should input your module's IP
3. You may see that it shows the website is not able to be trusted, but you should select that "go on to visit it"
4. You should wait for a moment until your see the "OpenSSL server demo!" in your web browser
Note:
The private key and certification at the example are not trusted by web browser, because they are not created by CA official, just by ourselves.
You can alse create your own private key and ceritification by "openssl at ubuntu or others".
See the README.md file in the upper level 'examples' directory for more information about examples.

View file

@ -0,0 +1,15 @@
menu "Example Configuration"
config WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
endmenu

View file

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDezCCAmOgAwIBAgIJAPMMNobNczaUMA0GCSqGSIb3DQEBBAUAMHQxEzARBgNV
BAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEcMBoGCSqG
SIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0aWZpY2F0
aW9uIEF1dGhvcml0eTAeFw0xNjExMTUwNTA0MThaFw0xOTExMTUwNTA0MThaMHQx
EzARBgNVBAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEc
MBoGCSqGSIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0
aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALDjSPDlomepHCzbw4MUrquQAU0xTV4/Npb27k9I5TRVTjIoOs/5hNI2LPFW
e4CREx09ZrT8K3NFOBoSy7bhPAsjGaFxCYYWc9tiX1m5gq3ToVRSmbZ65fE3kvnI
8E/d5VyzA0OMmWbfaolBSTMoWgqRynEaT+z1Eh2yDTzVFy9eov1DdQFUqGDqbH5b
QYvTY5Fyem7UcKWAe2yS0j3H4dVtVBKNY7qV3Px08yGAs5fQFgUwhyB5+qwhvkeL
JdgapGaSTwLgoQKWHbe/lA3NiBIB9hznFUGKo3hmniAvYZbrQcn3tc0l/J4I39v2
Pm29FAyjWvQyBkGktz2q4elOZYkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq
hkiG9w0BAQQFAAOCAQEAJCJ+97oae/FcOLbPpjCpUQnWqYydgSChgalkZNvr4fVp
TnuNg471l0Y2oTJLoWn2YcbPSFVOEeKkU47mpjMzucHHp0zGaW9SdzhZalWwmbgK
q2ijecIbuFHFNedYTk/03K7eaAcjVhD8e0oOJImeLOL6DAFivA1LUnSgXsdGPDtD
zhISsCPTu+cL1j0yP6HBvLeAyb8kaCWJ05RtiVLRANNHQn/keHajJYpMwnEEbJdG
cqN3whfJoGVbZ6isEf2RQJ0pYRnP7uGLW3wGkLWxfdto8uER8HVDx7fZpevLIqGd
1OoSEi3cIJXWBAjx0TLzzhtb6aeIxBJWQqHThtkKdg==
-----END CERTIFICATE-----

View file

@ -0,0 +1,11 @@
#
# Main Makefile. This is basically the same as a component makefile.
#
# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default,
# this will take the sources in the src/ directory, compile them and link them into
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#
COMPONENT_EMBED_TXTFILES := cacert.pem
COMPONENT_EMBED_TXTFILES += prvtkey.pem

View file

@ -0,0 +1,258 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "openssl_server.h"
#include <string.h>
#include "openssl/ssl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_types.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "tcpip_adapter.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
static EventGroupHandle_t wifi_event_group;
/* The event group allows multiple bits for each event,
but we only care about one event - are we connected
to the AP with an IP? */
const static int CONNECTED_BIT = BIT0;
const static char *TAG = "Openssl_demo";
#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \
"Content-Type: text/html\r\n" \
"Content-Length: 98\r\n" \
"<html>\r\n" \
"<head>\r\n" \
"<title>OpenSSL demo</title></head><body>\r\n" \
"OpenSSL server demo!\r\n" \
"</body>\r\n" \
"</html>\r\n"
static void openssl_demo_thread(void *p)
{
int ret;
SSL_CTX *ctx;
SSL *ssl;
int socket, new_socket;
socklen_t addr_len;
struct sockaddr_in sock_addr;
char send_data[] = OPENSSL_DEMO_SERVER_ACK;
int send_bytes = sizeof(send_data);
char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN];
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start;
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
const unsigned int prvtkey_pem_bytes = prvtkey_pem_end - prvtkey_pem_start;
ESP_LOGI(TAG, "SSL server context create ......");
ctx = SSL_CTX_new(SSLv3_server_method());
if (!ctx) {
ESP_LOGI(TAG, "failed");
goto failed1;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server context set own certification......");
ret = SSL_CTX_use_certificate_ASN1(ctx, cacert_pem_bytes, cacert_pem_start);
if (!ret) {
ESP_LOGI(TAG, "failed");
goto failed2;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server context set private key......");
ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, prvtkey_pem_start, prvtkey_pem_bytes);
if (!ret) {
ESP_LOGI(TAG, "failed");
goto failed2;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server create socket ......");
socket = socket(AF_INET, SOCK_STREAM, 0);
if (socket < 0) {
ESP_LOGI(TAG, "failed");
goto failed2;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server 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(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
if (ret) {
ESP_LOGI(TAG, "failed");
goto failed3;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server socket listen ......");
ret = listen(socket, 32);
if (ret) {
ESP_LOGI(TAG, "failed");
goto failed3;
}
ESP_LOGI(TAG, "OK");
reconnect:
ESP_LOGI(TAG, "SSL server create ......");
ssl = SSL_new(ctx);
if (!ssl) {
ESP_LOGI(TAG, "failed");
goto failed3;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server socket accept client ......");
new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len);
if (new_socket < 0) {
ESP_LOGI(TAG, "failed" );
goto failed4;
}
ESP_LOGI(TAG, "OK");
SSL_set_fd(ssl, new_socket);
ESP_LOGI(TAG, "SSL server accept client ......");
ret = SSL_accept(ssl);
if (!ret) {
ESP_LOGI(TAG, "failed");
goto failed5;
}
ESP_LOGI(TAG, "OK");
ESP_LOGI(TAG, "SSL server read message ......");
do {
memset(recv_buf, 0, OPENSSL_DEMO_RECV_BUF_LEN);
ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1);
if (ret <= 0) {
break;
}
if (strstr(recv_buf, "GET / HTTP/1.1")) {
SSL_write(ssl, send_data, send_bytes);
break;
}
} while (1);
ESP_LOGI(TAG, "result %d", ret);
SSL_shutdown(ssl);
failed5:
close(new_socket);
new_socket = -1;
failed4:
SSL_free(ssl);
ssl = NULL;
goto reconnect;
failed3:
close(socket);
socket = -1;
failed2:
SSL_CTX_free(ctx);
ctx = NULL;
failed1:
vTaskDelete(NULL);
return ;
}
static void openssl_client_init(void)
{
int ret;
xTaskHandle openssl_handle;
extern void openssl_demo_thread(void *p);
ret = xTaskCreate(openssl_demo_thread,
OPENSSL_DEMO_THREAD_NAME,
OPENSSL_DEMO_THREAD_STACK_WORDS,
NULL,
OPENSSL_DEMO_THREAD_PRORIOTY,
&openssl_handle);
if (ret != pdPASS) {
ESP_LOGI(TAG, "create thread %s failed", OPENSSL_DEMO_THREAD_NAME);
return ;
}
}
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
openssl_client_init();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
/* This is a workaround as ESP32 WiFi libs don't currently
auto-reassociate. */
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
static void wifi_conn_init(void)
{
tcpip_adapter_init();
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK( esp_event_loop_init(wifi_event_handler, NULL) );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_WIFI_SSID,
.password = EXAMPLE_WIFI_PASS,
},
};
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]\n", EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS);
ESP_ERROR_CHECK( esp_wifi_start() );
}
void app_main(void)
{
nvs_flash_init();
wifi_conn_init();
}

View file

@ -0,0 +1,22 @@
#ifndef _OPENSSL_DEMO_H_
#define _OPENSSL_DEMO_H_
/* The examples use simple WiFi configuration that you can set via
'make menuconfig'.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
#define OPENSSL_DEMO_THREAD_NAME "OpenSSL_demo"
#define OPENSSL_DEMO_THREAD_STACK_WORDS 10240
#define OPENSSL_DEMO_THREAD_PRORIOTY 8
#define OPENSSL_DEMO_RECV_BUF_LEN 1024
#define OPENSSL_DEMO_LOCAL_TCP_PORT 443
#endif

View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsONI8OWiZ6kcLNvDgxSuq5ABTTFNXj82lvbuT0jlNFVOMig6
z/mE0jYs8VZ7gJETHT1mtPwrc0U4GhLLtuE8CyMZoXEJhhZz22JfWbmCrdOhVFKZ
tnrl8TeS+cjwT93lXLMDQ4yZZt9qiUFJMyhaCpHKcRpP7PUSHbINPNUXL16i/UN1
AVSoYOpsfltBi9NjkXJ6btRwpYB7bJLSPcfh1W1UEo1jupXc/HTzIYCzl9AWBTCH
IHn6rCG+R4sl2BqkZpJPAuChApYdt7+UDc2IEgH2HOcVQYqjeGaeIC9hlutByfe1
zSX8ngjf2/Y+bb0UDKNa9DIGQaS3Parh6U5liQIDAQABAoIBAB9K9jp3xXVlO3DM
KBhmbkg3n6NSV4eW00d9w8cO9E1/0eeZql3knJS7tNO1IwApqiIAHM1j1yP7WONz
88oUqpSlzwD6iF7KVhC3pHqxEOdDi0Tpn/viXg+Ab2X1IF5guRTfLnKiyviiCazi
edqtBtDb3d6Icx9Oc7gBKcpbQFDGt++wSOb5L+xhRm9B5B4l/6byikiPeKqIK5tC
SoP9Zr1mvpNoGm1P4LvEunFJcRBqVI010VNwfO9P98oVyzJu9/FZZrQxXoY9JdXF
OM6nbl+hMDM3TkEOda9NvBhImozEAvuc97CaaXyR3XivxMqNqNIb4+syUPa2PCS3
ZztI5qECgYEA1gbVG6ifpvpbBkDPi3Im8fM3F7FLLrQc48FdFjdMvDhHD9lVKucD
Uaa8PF9dbbvlu2cwMyfBOKSuWaXxRxRsiqiPmTunS1MvPzQcSrGwUrL2AogGucn6
+NrLQf5P4H5IpkDQ9ih3zwjO6xKFK1WeYnYpHM8qUBtl6q0YFyVBPu0CgYEA05Pn
StWA4D7VSbNnVi6lvFyEOUsTrK3v419598TFiq4eXLq6aV8/CQYzKsSzoG+aOZhX
Li+0uyT5cNzUcXYhTsW1hA/pNhMfxMrYiB1x14zlLp2WRGg4vd/+SxX6d9Yd3acX
7QzPKgdDicXs9QN8ozJOICKvNbUI53AJdATVEY0CgYEAwvpGeoQLrdq1weSZLrg3
soOX1QW3MDz1dKdbXjnStkWut0mOxR7fbysuoPFf8/ARQcCnsHKvHCMqkpESVWbN
2yPkbfxiU8Tcbf/TJljqAOz4ISY6ula/RKZONTixHBrvpEW4GAiV3Q5xMsYUe33s
ZFaw7YXtTj0ng7tdDvjpj6ECgYEApHdUU9ejVq2BHslWiqe4LbO9FMxHfvO2hgix
xugupp6y+2Irhb2EQn+PRq+g8hXOzPaezkhHNTKItDL08T3iplkJwJ6dqmszRsZn
i2dYFzZu8M2PAZ4CfZahFbz/9id7D9HTx3EtmH4NAgvZJpyPRkzUbiaIDDettDpj
Hsyi1AECgYAPLvjBzQj4kPF8Zo9pQEUcz4pmupRVfv3aRfjnahDK4qZHEePDRj+J
W7pzayrs1dyN9QLB8pTc424z7f8MB3llCICN+ohs8CR/eW0NEobE9ldDOeoCr1Vh
NhNSbrN1iZ8U4oLkRTMaDKkVngGffvjGi/q0tOU7hJdZOqNlk2Iahg==
-----END RSA PRIVATE KEY-----