From 794b4ff578c6c79416d616659250299d6eab087b Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Mon, 14 Nov 2016 15:11:22 +0800 Subject: [PATCH] components/openssl: add client and server demo --- examples/09_openssl/Makefile | 9 + examples/09_openssl/README.md | 21 + examples/09_openssl/main/Kconfig.projbuild | 27 ++ examples/09_openssl/main/component.mk | 10 + examples/09_openssl/main/openssl_demo.c | 430 +++++++++++++++++++++ examples/09_openssl/main/openssl_demo.h | 66 ++++ 6 files changed, 563 insertions(+) create mode 100644 examples/09_openssl/Makefile create mode 100644 examples/09_openssl/README.md create mode 100644 examples/09_openssl/main/Kconfig.projbuild create mode 100644 examples/09_openssl/main/component.mk create mode 100644 examples/09_openssl/main/openssl_demo.c create mode 100644 examples/09_openssl/main/openssl_demo.h diff --git a/examples/09_openssl/Makefile b/examples/09_openssl/Makefile new file mode 100644 index 000000000..8987be554 --- /dev/null +++ b/examples/09_openssl/Makefile @@ -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 + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/09_openssl/README.md b/examples/09_openssl/README.md new file mode 100644 index 000000000..54b013342 --- /dev/null +++ b/examples/09_openssl/README.md @@ -0,0 +1,21 @@ +# Openssl Example + +The Example contains of OpenSSL client and server demo. + +First you should config the project by "menuconfig": + Example Configuration -> + 1. Openssl demo: select your demo (client or server) + 2. WiFi SSID: you own wifi, which you pc is connected to alse. + 3. WiFi Password: wifi password + +If you want to test the OpenSSL client demo: + 1. compile the code and load the firmware + 2. you can see it will download the "www.baidu.com" main page and print the context + +IF you want to test the openSSL client demo: + 1. compile the code and load the firmware + 2. You should input the context of "https://192.168.17.128", 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 IE page + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/09_openssl/main/Kconfig.projbuild b/examples/09_openssl/main/Kconfig.projbuild new file mode 100644 index 000000000..b42529ca1 --- /dev/null +++ b/examples/09_openssl/main/Kconfig.projbuild @@ -0,0 +1,27 @@ +menu "Example Configuration" + +choice OPENSSL_DEMO + prompt "Openssl demo" + default OPENSSL_CLIENT_DEMO + help + Openssl test demo mode, client or server. + +config OPENSSL_CLIENT_DEMO + bool "client demo" +config OPENSSL_SERVER_DEMO + bool "server demon" +endchoice + +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 "myssid" + help + WiFi password (WPA or WPA2) for the example to use. + +endmenu \ No newline at end of file diff --git a/examples/09_openssl/main/component.mk b/examples/09_openssl/main/component.mk new file mode 100644 index 000000000..24356f23e --- /dev/null +++ b/examples/09_openssl/main/component.mk @@ -0,0 +1,10 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(SDK_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. +# + +include $(IDF_PATH)/make/component_common.mk diff --git a/examples/09_openssl/main/openssl_demo.c b/examples/09_openssl/main/openssl_demo.c new file mode 100644 index 000000000..d541b2625 --- /dev/null +++ b/examples/09_openssl/main/openssl_demo.c @@ -0,0 +1,430 @@ +#include +#include + +#include "openssl_demo.h" +#include "openssl/ssl.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_types.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" + +#include "lwip/sockets.h" +#include "lwip/api.h" + +#include "nvs_flash.h" + + +#define os_printf(fmt, ...) ESP_LOGI("openssl_demo", fmt, ##__VA_ARGS__) + +#define IP_ADDR(ip) ip.u_addr.ip4.addr + +/* 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_STACK_WORDS 8192 +#define OPENSSL_DEMO_THREAD_PRORIOTY 6 + +#define OPENSSL_DEMO_FRAGMENT_SIZE 8192 + +#define OPENSSL_DEMO_RECV_BUF_LEN 1024 + +#define OPENSSL_DEMO_LOCAL_TCP_PORT 443 + +#ifdef CONFIG_OPENSSL_CLIENT_DEMO + +#define OPENSSL_DEMO_THREAD_NAME "ssl_client" + +#define OPENSSL_DEMO_TARGET_NAME "www.baidu.com" +#define OPENSSL_DEMO_TARGET_TCP_PORT 443 + +#define OPENSSL_DEMO_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" + +LOCAL void openssl_demo_thread(void *p) +{ + int ret; + + SSL_CTX *ctx; + SSL *ssl; + + int socket; + struct sockaddr_in sock_addr; + + ip_addr_t target_ip; + + int recv_bytes = 0; + + LOCAL char send_data[] = OPENSSL_DEMO_REQUEST; + LOCAL int send_bytes = sizeof(send_data); + + LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + os_printf("OpenSSL demo thread start\n"); + + do { + ret = netconn_gethostbyname(OPENSSL_DEMO_TARGET_NAME, &target_ip); + } while(ret); + os_printf("get target IP is %d.%d.%d.%d\n", + (unsigned char)((IP_ADDR(target_ip) & 0x000000ff) >> 0), + (unsigned char)((IP_ADDR(target_ip) & 0x0000ff00) >> 8), + (unsigned char)((IP_ADDR(target_ip) & 0x00ff0000) >> 16), + (unsigned char)((IP_ADDR(target_ip) & 0xff000000) >> 24)); + + os_printf("create SSL context ......"); + ctx = SSL_CTX_new(TLSv1_1_client_method()); + if (!ctx) { + os_printf("failed\n"); + goto failed1; + } + os_printf("OK\n"); + + /** + * The openssl does not support "SSL_CTX_set_default_read_buffer_len" + * at the platform of ESP32 esp_idf now. + * + * So you should not care it now. And We my let it work later. + */ + os_printf("set SSL context read buffer size ......"); + SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); + ret = 0; + if (ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + + os_printf("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_DEMO_LOCAL_TCP_PORT); + ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + os_printf("failed\n"); + goto failed4; + } + os_printf("OK\n"); + + os_printf("socket connect to remote %s ......", OPENSSL_DEMO_TARGET_NAME); + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = IP_ADDR(target_ip); + sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); + ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + if (ret) { + os_printf("failed\n"); + goto failed5; + } + os_printf("OK\n"); + + os_printf("create SSL ......"); + ssl = SSL_new(ctx); + if (!ssl) { + os_printf("failed\n"); + goto failed6; + } + os_printf("OK\n"); + + SSL_set_fd(ssl, socket); + + os_printf("SSL connected to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_connect(ssl); + if (!ret) { + os_printf("failed, return [-0x%x]\n", -ret); + goto failed7; + } + os_printf("OK\n"); + + os_printf("send https request to %s port %d ......", + OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); + ret = SSL_write(ssl, send_data, send_bytes); + if (ret <= 0) { + os_printf("failed\n"); + goto failed8; + } + os_printf("OK\n\n"); + + do { + ret = SSL_read(ssl, recv_buf, OPENSSL_DEMO_RECV_BUF_LEN - 1); + if (ret <= 0) { + break; + } + recv_bytes += ret; + os_printf("%s", recv_buf); + } while (1); + + os_printf("\r\ntotaly read %d bytes data from %s ......\n", recv_bytes, OPENSSL_DEMO_TARGET_NAME); + +failed8: + SSL_shutdown(ssl); +failed7: + SSL_free(ssl); + ssl = NULL; +failed6: +failed5: +failed4: + close(socket); + socket = -1; +failed3: +failed2: + SSL_CTX_free(ctx); + ctx = NULL; +failed1: + vTaskDelete(NULL); + + os_printf("task exit\n"); + + return ; +} + +#elif defined(CONFIG_OPENSSL_SERVER_DEMO) + +#define OPENSSL_DEMO_THREAD_NAME "openssl_server" + +#define OPENSSL_DEMO_CLIENT_REQUEST "{\"path\": \"/v1/ping/\", \"method\": \"GET\"}\r\n" + +#define OPENSSL_DEMO_SERVER_ACK "HTTP/1.1 200 OK\r\n" \ + "Content-Type: text/html\r\n" \ + "Content-Length: 98\r\n" \ + "\r\n" \ + "\r\n" \ + "openSSL demo\r\n" \ + "OpenSSL server demo!\r\n" \ + "\r\n" \ + "\r\n" + +LOCAL 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; + + LOCAL char send_data[] = OPENSSL_DEMO_SERVER_ACK; + LOCAL int send_bytes = sizeof(send_data); + + LOCAL char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; + + os_printf("server SSL context create ......"); + ctx = SSL_CTX_new(SSLv3_server_method()); + if (!ctx) { + os_printf("failed\n"); + goto failed1; + } + os_printf("OK\n"); + + /** + * The openssl does not support "SSL_CTX_set_default_read_buffer_len" + * at the platform of ESP32 esp_idf now. + * + * So you should not care it now. And We my let it work later. + */ + os_printf("server SSL context set fragment ......"); + SSL_CTX_set_default_read_buffer_len(ctx, OPENSSL_DEMO_FRAGMENT_SIZE); + ret = 0; + if (ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server SSL context set own certification......"); + ret = SSL_CTX_use_certificate_ASN1(ctx, cert_bytes, cert_ctx); + if (!ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server SSL context set private key......"); + ret = SSL_CTX_use_PrivateKey_ASN1(0, ctx, key_ctx, key_bytes); + if (!ret) { + os_printf("failed, return %d\n", ret); + goto failed2; + } + os_printf("OK\n"); + + os_printf("server create socket ......"); + socket = socket(AF_INET, SOCK_STREAM, 0); + if (socket < 0) { + os_printf("failed\n"); + goto failed2; + } + os_printf("OK\n"); + + os_printf("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) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + + os_printf("server socket listen ......"); + ret = listen(socket, 32); + if (ret) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + +reconnect: + os_printf("server SSL create ......"); + ssl = SSL_new(ctx); + if (!ssl) { + os_printf("failed\n"); + goto failed3; + } + os_printf("OK\n"); + + os_printf("server socket accept client ......"); + new_socket = accept(socket, (struct sockaddr *)&sock_addr, &addr_len); + if (new_socket < 0) { + os_printf("failed, return [-0x%x]\n", -new_socket); + goto failed4; + } + os_printf("OK\n"); + + SSL_set_fd(ssl, new_socket); + + os_printf("server SSL accept client ......"); + ret = SSL_accept(ssl); + if (!ret) { + os_printf("failed\n"); + goto failed5; + } + os_printf("OK\n"); + + os_printf("server SSL 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); + + os_printf("result %d\n", 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 ; +} + +#else + #error "you must choose the right demo type" +#endif + +LOCAL void demo_init(void) +{ + int ret = pdFALSE; + +#if defined(CONFIG_OPENSSL_CLIENT_DEMO) || defined(CONFIG_OPENSSL_SERVER_DEMO) + xTaskHandle openssl_handle; + + ret = xTaskCreate(openssl_demo_thread, + OPENSSL_DEMO_THREAD_NAME, + OPENSSL_DEMO_THREAD_STACK_WORDS, + NULL, + OPENSSL_DEMO_THREAD_PRORIOTY, + &openssl_handle); +#endif + + if (ret != pdPASS) { + os_printf("create thread %s failed\n", OPENSSL_DEMO_THREAD_NAME); + return ; + } +} + +LOCAL 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: + demo_init(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + break; + default: + break; + } + return ESP_OK; +} + +LOCAL void wifi_conn_init(void) +{ + tcpip_adapter_init(); + 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) ); + os_printf("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(); +} + diff --git a/examples/09_openssl/main/openssl_demo.h b/examples/09_openssl/main/openssl_demo.h new file mode 100644 index 000000000..89cd264b4 --- /dev/null +++ b/examples/09_openssl/main/openssl_demo.h @@ -0,0 +1,66 @@ +#ifndef _OPENSSL_DEMO_H_ +#define _OPENSSL_DEMO_H_ + +const static unsigned char key_ctx[] = + "-----BEGIN PRIVATE KEY-----\r\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQyyF0WBb2XbkL\r\n" + "wYFgyoPOanYvbb/qwbAkGf1zSPX35xruZmjszjcverMoyF6x2MBxD3gP1ijBR0Rr\r\n" + "0J0CfluABDLkzqpF5smOVX9k8W7ePClm91NhcASuF+CaZOe6B+6vOYShYjhe6eFG\r\n" + "AGk8SP4zSrG2XHNKXlR3w8duK9fyOOZLWRjL3T6+++HEaly1p4ujKZhrm5wHzywA\r\n" + "DvjDdvIWBCW1Z+8j7Q9qUITjlsDWHjrXCpyEfclE1WQxTP/W7rBLxNVxTfwbrdcD\r\n" + "HNrKTOXtN+oDmCruvmBnTkz9x4Te6wJuvtFd0fBtW1kWsMzomvOlKmvHo0gmpqfh\r\n" + "CwEPoKCNAgMBAAECggEBAIVr+LHXBL1kQLZhbiKC5t1FrMY8FLKYGM3JCevciMlk\r\n" + "lhIXwR7p29vsRYZfHBv7zWWyI9/C04JG31MiGOMaCbBxfnA2HBrVEqFwwxqnKVi8\r\n" + "CxzwGQkfwu3Y9j7TEj0PipfQYo+aKzmDrN/FrXnHjyEJryxAQbAZPVLW+Z7OR41R\r\n" + "ZOwtZLeVqmbeARGpu2Xd9SKAhbjdLSz96IdUcNrwbP/lzUgrKaiUioBMVFfIG5ce\r\n" + "4Mm2seCwaWxI8k24q0keSjsjV+5IxatVUNtJ9vYv6Tzo+3oqGvPeUBO7w9xhbLKf\r\n" + "jw1uEykcs0wcftWb1iB7r78bMPZ/KYhnSFsjT+vnIOECgYEA9LM5p63sn6OWrULd\r\n" + "doBBLaIw1ZK9rDUFLLRwv0e6+7tuuB08ok6D7PSfOpx0bb10lIx7epOE8ogGSmLS\r\n" + "w0rMbmcKAlTLAJ/0nX1ierZkb+Ay21F398tKL3igEfnaB9CzuOHF8XhbsTqeGFDJ\r\n" + "HFBMXxTbo4kfkUmZNYxwTombzkkCgYEA2m9teqjEOVZItqghOicWZ68JhWxBJFme\r\n" + "oSfzJKLd8atfUOnBLqAhPzvg1PvdIxjLWBqy28tEJf+jdSQCNe9BmhlptOwbFrJy\r\n" + "IyCXj6QTApSKTxyzIjMvzQkv1m8CxeCq5T64hvJ2++i7dlhumh21c7oL8aLeTnoe\r\n" + "AG1dBLJ9UCUCgYAhSlDJsyvB/Ct/nt0qRgCYCLzEEZakWwI9Nr8wBr41iSZi/fdF\r\n" + "zZC9J/qRqr9cPq4hl4sk/fTUWhUhAZjS4NY3HuWJs6d6ikhpNKm1MCMx5TqGA+ti\r\n" + "VtHc63g7edZjwczxliWr2EgBMIxZmoQByhrZxKis8vbMeUrSsiyFQstjoQKBgD3k\r\n" + "2Paqn39Hra7kERYzQSv78wy1UfgE1OgBM+orpAv4bTe2JKEbipAqXVi8TTrGqce7\r\n" + "OPcCr7q8pwpoO6AgvUv263byd/KEecbuU0PGUASpJk+oaDHGo0LL2Zw/NF/xezsd\r\n" + "/JdwWLqkhYnRIPXWeTXjf8LmTWubOqkQVA0irlNpAoGAJ+9N/NF3XAW0BroiVYLZ\r\n" + "p0Btcgt+b4LWrBlm0XqHhzKUlqhfibAr3OtUkFjo/509ncYPiuOzVSNosyjXFJ86\r\n" + "2kQ88fB3eeLnBAcbBXQKiOBPU2y6bCCfgdo+JEOK/cxVslaxMAyKSnFi9gdgzScd\r\n" + "k+hOlkflXQVkic3W358kFto=\r\n" + "-----END PRIVATE KEY-----\r\n" + ; +static int key_bytes = sizeof(key_ctx); + +const static unsigned char cert_ctx[] = + "-----BEGIN CERTIFICATE-----\r\n" + "MIID7jCCAtYCAQEwDQYJKoZIhvcNAQELBQAwgbwxCzAJBgNVBAYTAkNOMRAwDgYD\r\n" + "VQQIDAdKaWFuZ3N1MQ0wCwYDVQQHDARXdXhpMSYwJAYDVQQKDB1Fc3ByZXNzaWYg\r\n" + "Um9vdCBSU0EyMDQ4IHNoYTI1NjEcMBoGA1UECwwTUm9vdCBSU0EyMDQ4IHNoYTI1\r\n" + "NjEfMB0GA1UEAwwWcm9vdGNlcnQuZXNwcmVzc2lmLmNvbTElMCMGCSqGSIb3DQEJ\r\n" + "ARYWcm9vdGNlcnRAZXNwcmVzc2lmLmNvbTAeFw0xNjA2MjgwMjMxMjlaFw0yNjA2\r\n" + "MjYwMjMxMjlaMIG8MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdzdTENMAsG\r\n" + "A1UEBwwEV3V4aTEmMCQGA1UECgwdRXNwcmVzc2lmIFJvb3QgUlNBMjA0OCBzaGEy\r\n" + "NTYxHDAaBgNVBAsME1Jvb3QgUlNBMjA0OCBzaGEyNTYxHzAdBgNVBAMMFnJvb3Rj\r\n" + "ZXJ0LmVzcHJlc3NpZi5jb20xJTAjBgkqhkiG9w0BCQEWFnJvb3RjZXJ0QGVzcHJl\r\n" + "c3NpZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQyyF0WBb2\r\n" + "XbkLwYFgyoPOanYvbb/qwbAkGf1zSPX35xruZmjszjcverMoyF6x2MBxD3gP1ijB\r\n" + "R0Rr0J0CfluABDLkzqpF5smOVX9k8W7ePClm91NhcASuF+CaZOe6B+6vOYShYjhe\r\n" + "6eFGAGk8SP4zSrG2XHNKXlR3w8duK9fyOOZLWRjL3T6+++HEaly1p4ujKZhrm5wH\r\n" + "zywADvjDdvIWBCW1Z+8j7Q9qUITjlsDWHjrXCpyEfclE1WQxTP/W7rBLxNVxTfwb\r\n" + "rdcDHNrKTOXtN+oDmCruvmBnTkz9x4Te6wJuvtFd0fBtW1kWsMzomvOlKmvHo0gm\r\n" + "pqfhCwEPoKCNAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABTYZLiFHq51lqaa0nHI\r\n" + "aDMAb29DfO93fqp+oHZYO4xKyEeLr8EhD39GjnQmhz710wO0TBCYV7nD+xnJ1h5F\r\n" + "IbQUAQZO9NIy3ns4mYVRUWjnWYAo+evGeKgRrxvh7sjNLPBPzs9tg/u7XjBp/nor\r\n" + "8JnnFFT0wXPyi/qg8J3QutqJvWRQGRRx2AP93F44+Zcj7ReFMVSmOXyzT4aNJL0+\r\n" + "Ls+baKwA4pnyVRoAaKbs/JYDgd0/DunuktVKuhyvK/qOGjJSRLPhdrXbvSAegpiM\r\n" + "4xIm6ZWKtTv8VvkGgXUVQ7RpruP6nV6506gDcUgecbEq7H2VDhEzUYcMmGCUQZlG\r\n" + "sJ8=\r\n" + "-----END CERTIFICATE-----\r\n" + ; +static int cert_bytes = sizeof(cert_ctx); + + + +#endif