diff --git a/.github/workflows/build-examples-master.yml b/.github/workflows/build-examples-master.yml index bd6e035..885cbf6 100644 --- a/.github/workflows/build-examples-master.yml +++ b/.github/workflows/build-examples-master.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - for-iotsa jobs: build-examples: strategy: @@ -27,11 +28,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout codebase - uses: actions/checkout@f90c7b395dac7c5a277c1a6d93d5057c1cddb74e + uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@9ac730844c47e52575257e93faf193c4530bc095 + uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Install PlatformIO run: | python -m pip install --upgrade pip diff --git a/.github/workflows/build-examples-pr.yml b/.github/workflows/build-examples-pr.yml index b3d67a5..3953fed 100644 --- a/.github/workflows/build-examples-pr.yml +++ b/.github/workflows/build-examples-pr.yml @@ -27,9 +27,9 @@ jobs: if: "contains( github.event.pull_request.labels.*.name, 'CI: Build Examples' )" steps: - name: Checkout codebase - uses: actions/checkout@f90c7b395dac7c5a277c1a6d93d5057c1cddb74e + uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@9ac730844c47e52575257e93faf193c4530bc095 + uses: actions/setup-python@v4 with: python-version: '3.8' - name: Install PlatformIO @@ -43,7 +43,7 @@ jobs: if: "contains( github.event.pull_request.labels.*.name, 'CI: Build Examples' )" steps: - name: Remove Label from PR - uses: octokit/request-action@57ec46afcc4c58c813af3afe67e57ced1ea9f165 + uses: octokit/request-action@91508edec0a9561c2fefb9282491ced243bed312 with: route: DELETE /repos/:repository/issues/:issue_number/labels/:name repository: ${{ github.repository }} diff --git a/CHANGELOG.md b/CHANGELOG.md index f9ba97b..4b48fbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,13 @@ # Changelog -## [pending (master)](https://github.com/fhessel/esp32_https_server/tree/master) +## [v1.1.1](https://github.com/jackjansen/esp32_idf5_https_server/tree/master) -New functionality: - -– - -Bug fixes: - -– +- Addressed issues with esp32-arduino-core v3 and esp-idf 5.0 -Breaking changes: +## [v1.1.0](https://github.com/jackjansen/esp32_idf5_https_server/tree/master) -– +- Compatible with ESP-IDF 5.0 +- Use esp-tls in stead of openssl ## [v1.0.0](https://github.com/fhessel/esp32_https_server/releases/tag/v1.0.0) diff --git a/README.md b/README.md index 33773dd..c59d61e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,14 @@ -# ESP32 HTTPS Server +# ESP32 HTTPS Server, IDF5 fork -![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/fhessel/esp32_https_server?label=Version&sort=semver) ![Build Examples](https://github.com/fhessel/esp32_https_server/workflows/Build%20Examples/badge.svg?branch=master) +This repository is a fork of `fhessel/esp32_https_server`. The only reason for its existence is that it seems _fhessel_ currently does not have the time to maintain `esp32_https_server`, and due to changes in the underlying Espressif frameworks such as `ESP_IDF` it has stopped working. + +This forked repository has just enough changes so that the library works. It is hoped that it will go away in the future (after a warning period) when `esp32_idf_server` maintainance is picked up again. + +In the following instructions + +- replace every mention of `esp32_https_server` with `esp32_idf5_https_server` + +## Original readme of esp32_https_server This repository contains an HTTPS server library that can be used with the [ESP32 Arduino Core](https://github.com/espressif/arduino-esp32). It supports HTTP as well. diff --git a/boards/esp32-s3-devkitc-1-32MB-8MB.json b/boards/esp32-s3-devkitc-1-32MB-8MB.json new file mode 100644 index 0000000..2178f80 --- /dev/null +++ b/boards/esp32-s3-devkitc-1-32MB-8MB.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "large_littlefs_32MB.csv", + "memory_type": "opi_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "boot": "opi", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitC-2-opi", + "upload": { + "flash_size": "32MB", + "maximum_ram_size": 327680, + "maximum_size": 33554432, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", + "vendor": "Espressif" +} \ No newline at end of file diff --git a/example.conf b/example.conf new file mode 100644 index 0000000..01f46b1 --- /dev/null +++ b/example.conf @@ -0,0 +1,9 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +[ req_distinguished_name ] +C = DE +ST = BE +L = Berlin +O = MyCompany +CN = esp32.local diff --git a/example.crt b/example.crt new file mode 100644 index 0000000..a27ff33 --- /dev/null +++ b/example.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJERTEL +MAkGA1UECAwCQkUxDzANBgNVBAcMBkJlcmxpbjESMBAGA1UECgwJTXlDb21wYW55 +MRMwEQYDVQQDDApteWNhLmxvY2FsMB4XDTI0MDcwOTEwMTEwN1oXDTM0MDcwNzEw +MTEwN1owVTELMAkGA1UEBhMCREUxCzAJBgNVBAgMAkJFMQ8wDQYDVQQHDAZCZXJs +aW4xEjAQBgNVBAoMCU15Q29tcGFueTEUMBIGA1UEAwwLZXNwMzIubG9jYWwwgZ8w +DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK/aY9jhRfEAgfu3KeTNQ1T2CshDP12e +benmLPnnVG830HQhMLIe1itN/f0tPTguUYtOBgUS9w2zeZEdm6aqeskkkV55Wnmz +IhGNg/cuwl/zp98NbOsZ4Rwcjp5dtL5w8UnlIsK8PsFntRWHQOthgaKH3YzyGg65 +ZtPKD13/ZGXbAgMBAAGjQjBAMB0GA1UdDgQWBBTBnWcv/0066SQSwr7nvZc0bg8B +fzAfBgNVHSMEGDAWgBTCqpgyA21IXR4Maq4makkkGgy66TANBgkqhkiG9w0BAQsF +AAOBgQAV0W4470+7/P5bRd94GYyF16/DR1W/H4NITptAJsMGjdyOaRVQnebCYP73 +idqMu9LUk0XGqG7StMys5n0VatMjhqOKrZF67wYEgGlaPYTRfpHEDMCPDLB/myYC +OpkxBG45CHzNz2tABRxsfPXN4+8bZpz0y6LUoeQD/ZMcMmZ2sA== +-----END CERTIFICATE----- diff --git a/example.csr b/example.csr new file mode 100644 index 0000000..502a6d2 --- /dev/null +++ b/example.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBlDCB/gIBADBVMQswCQYDVQQGEwJERTELMAkGA1UECAwCQkUxDzANBgNVBAcM +BkJlcmxpbjESMBAGA1UECgwJTXlDb21wYW55MRQwEgYDVQQDDAtlc3AzMi5sb2Nh +bDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr9pj2OFF8QCB+7cp5M1DVPYK +yEM/XZ5t6eYs+edUbzfQdCEwsh7WK039/S09OC5Ri04GBRL3DbN5kR2bpqp6ySSR +XnlaebMiEY2D9y7CX/On3w1s6xnhHByOnl20vnDxSeUiwrw+wWe1FYdA62GBoofd +jPIaDrlm08oPXf9kZdsCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4GBAH3cG2NfDS4+ +bwqtP8Jignr/jUxlPnlVJj5dlnry0DYvf+RZBpVMjzmbm3L/lEg/UQeCk6DwBEEZ +LacF8sjT/cMm6r3362SFFK/UfmgzpRL8EJIrNAkjEEcDwwb/iEMV31rirGeyTKS9 +0REzeyVcH/Iazg1HJsUQIvcuc9lNusli +-----END CERTIFICATE REQUEST----- diff --git a/example.key b/example.key new file mode 100644 index 0000000..969cdbf --- /dev/null +++ b/example.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK/aY9jhRfEAgfu3 +KeTNQ1T2CshDP12ebenmLPnnVG830HQhMLIe1itN/f0tPTguUYtOBgUS9w2zeZEd +m6aqeskkkV55WnmzIhGNg/cuwl/zp98NbOsZ4Rwcjp5dtL5w8UnlIsK8PsFntRWH +QOthgaKH3YzyGg65ZtPKD13/ZGXbAgMBAAECgYAYgZm6hqJFlKmIl5zp+sTwWR1l +jSGOfV6Z4u7PoLI+kYumM13i5LM587N6jcxjQOkyPZxPJrZxHVrKo1KmpklX9VAD +4BZzpBhDgWAsBW0xjx2DLPAkWQHsP0P71XSWonukZmyV9JKpX5/0zxuMKtc7AHAw +myWKq8xVMKQf4YbZKQJBAOMBp8k5xkK7t+WtGfkwTu1zweVAkjVx4YH+bjftn/fR +wFmak+yyuYb52kaT1rPHiWz4ABQW4YrYvB7qYejKyE0CQQDGUDEfAZEkjX3aTYFA +3FjUOUNn0ip/hKMKAUJa2u8ScNQE/L/5jAhDIuADMiHtEGhT55+N0FW0Oya/4MXG +hnrHAkBcucZhqdnUVH1vsd+ULClxUQF4tYGDlzr4MIexDL11KxaZA009OFwUSGbi +wWzIDs+R1VOi4R3L63AcaL0JrBtZAkAe4hIkP/w4cwhsXLGKRkZXFmvW2TXhEejK +ABQzTfD5MDT0aeADnrkSq3WzSbVa07lLh8CjNxSBssyACSMDnaG1AkEAxGfepmeQ +zmTCYXY2SJI2M8g5VfZTMqOawmnZfC8M9j5+/Co6smcYZnP7UrQ2ISuMCUpQHkMh +GZAnN8lsCt08PQ== +-----END PRIVATE KEY----- diff --git a/exampleca.conf b/exampleca.conf new file mode 100644 index 0000000..4074115 --- /dev/null +++ b/exampleca.conf @@ -0,0 +1,9 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +[ req_distinguished_name ] +C = DE +ST = BE +L = Berlin +O = MyCompany +CN = myca.local diff --git a/exampleca.crt b/exampleca.crt new file mode 100644 index 0000000..5d850d1 --- /dev/null +++ b/exampleca.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUjCCAbugAwIBAgIUfQMxSuNId0LHIA0ws5n78ThqLtIwDQYJKoZIhvcNAQEL +BQAwVDELMAkGA1UEBhMCREUxCzAJBgNVBAgMAkJFMQ8wDQYDVQQHDAZCZXJsaW4x +EjAQBgNVBAoMCU15Q29tcGFueTETMBEGA1UEAwwKbXljYS5sb2NhbDAeFw0yNDA3 +MDkxMDExMDdaFw0zNDA3MDcxMDExMDdaMFQxCzAJBgNVBAYTAkRFMQswCQYDVQQI +DAJCRTEPMA0GA1UEBwwGQmVybGluMRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNV +BAMMCm15Y2EubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPIbBuD+ +Q6dBjRK7bac9dpv4wp7o34S4hAsDUP8I/RVDB5BLaaAcxJKc9oaRcamxK8Ed3ybw +V8E3sI8s0+qmZ4UO+OxozGZqWSZGhzIN+2tL7UasRjysAIzfhDWTBGc+JzJoAHTs +Mq7F3uhE2vsjhZuo3cZ4kEk0hRIvnxpwAexVAgMBAAGjITAfMB0GA1UdDgQWBBTC +qpgyA21IXR4Maq4makkkGgy66TANBgkqhkiG9w0BAQsFAAOBgQA2xzOMllZTtSzR +4gcNsFVyIv9ddtFJhIg5UBBZgSPucjq+lfwnGCQl8HNl7k8RGtDOPKaRLYVlG20t +ZtBJJm+RODjRQQ+1AXwkS+/VodUhKXr4utgLMo8wtKUVUfNCwJ9Oa3lScgJVvEmT +y/qVdB3tFEjBEcGi4rm2HQK8ghZDhA== +-----END CERTIFICATE----- diff --git a/exampleca.key b/exampleca.key new file mode 100644 index 0000000..b21252c --- /dev/null +++ b/exampleca.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAPIbBuD+Q6dBjRK7 +bac9dpv4wp7o34S4hAsDUP8I/RVDB5BLaaAcxJKc9oaRcamxK8Ed3ybwV8E3sI8s +0+qmZ4UO+OxozGZqWSZGhzIN+2tL7UasRjysAIzfhDWTBGc+JzJoAHTsMq7F3uhE +2vsjhZuo3cZ4kEk0hRIvnxpwAexVAgMBAAECgYEA3cbIPF5uls5Dbn9m6SYyepob +nfnwluF3g6ccESOowktOqG2ManEv2KYUZhzho/J6BENa4Y6UtJhREjacQX0BoWeD +EwZ5QQBmgPK3FTlLStskGtp13zmotgSabmtP9laCu236XvCK3x+a/ylU8qgbnBbM +xbRXfFnRze0eCo9WCpkCQQD5qCgxb1IK1pIlwSuPOSP0uP6ydeFw5cYspLAGPpUH +3rZnKWj2aXPIGMN/ciQowvXoj9l1JgIEPrsrbgFLasTTAkEA+EHBB03mrclpHRSf +0aUrlkkS26DhKhlacNxRspywjnr2/4/FJxCFh0Lt7EYAOjYUcwqBgcBT4/YJYKQQ +U73xNwJAWO8wMjwHq9i4Az8G92RRjLIB+SzI/GC98dVQ50iP6lfJ/oHf5De4iQVZ +TyMoAmVBGHF186dwfHakUlpDl8wXBQJAQl3RrJI2yN6/KvcIgpMVQ+flErG/f/Gn +K+S6MnWQ/YYB4fAdVIQmLjLGSBOum+E5NkfotzcjNh3gA+XYN4rfoQJAY57SfWHe +4UPOuCcUs3/WJ16qfT2PrnFy80AD9L0dj8ZKe6LDRAVGHDTQ+aueo0cOGEDBdFhS +87ZipaBGxBV6Pw== +-----END PRIVATE KEY----- diff --git a/exampleca.srl b/exampleca.srl new file mode 100644 index 0000000..9e22bcb --- /dev/null +++ b/exampleca.srl @@ -0,0 +1 @@ +02 diff --git a/examples/Websocket-Chat/Websocket-Chat.ino b/examples/Websocket-Chat/Websocket-Chat.ino index 989c3b6..4c3f8ec 100644 --- a/examples/Websocket-Chat/Websocket-Chat.ino +++ b/examples/Websocket-Chat/Websocket-Chat.ino @@ -17,8 +17,10 @@ #include // TODO: Configure your WiFi here +#ifndef WIFI_SSID #define WIFI_SSID "" #define WIFI_PSK "" +#endif // Max clients to be connected to the chat #define MAX_CLIENTS 4 diff --git a/extras/create_cert.sh b/extras/create_cert.sh index 753fb03..a0d0e4e 100755 --- a/extras/create_cert.sh +++ b/extras/create_cert.sh @@ -1,5 +1,6 @@ #!/bin/bash set -e +set -x #------------------------------------------------------------------------------ # cleanup any previously created files rm -f exampleca.* example.* cert.h private_key.h diff --git a/library.json b/library.json index 0456c47..ef13400 100644 --- a/library.json +++ b/library.json @@ -1,14 +1,14 @@ { - "name": "esp32_https_server", + "name": "esp32_idf5_https_server", "keywords": "communication, esp32, http, https, server, ssl, tls, webserver, websockets", - "description": "Alternative ESP32 Webserver implementation for the ESP32, supporting HTTPS and HTTP. The library provides TLS support and simultaneous connections. It can be used to run an HTTP or HTTPS server, or both in parallel. The server's resources are defined through handler and middleware functions, giving an easy start to everyone who has worked with frameworks like Express or Servlets before.", + "description": "Alternative ESP32 Webserver implementation for the ESP32, supporting HTTPS and HTTP. The library provides TLS support and simultaneous connections. It can be used to run an HTTP or HTTPS server, or both in parallel. The server's resources are defined through handler and middleware functions, giving an easy start to everyone who has worked with frameworks like Express or Servlets before. This fork is compatible with ESP-IDF 5.0 or later.", "repository": { "type": "git", - "url": "https://github.com/fhessel/esp32_https_server.git" + "url": "https://github.com/jackjansen/esp32_idf5_https_server.git" }, "license": "MIT", - "version": "1.0.0", + "version": "1.1.1", "frameworks": "arduino", "platforms": ["espressif32"] } diff --git a/library.properties b/library.properties index 3ffb202..2d4b4e7 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ -name=ESP32_HTTPS_Server -version=1.0.0 +name=ESP32_IDF5_HTTPS_Server +version=1.1.1 author=Frank Hessel -maintainer=Frank Hessel -sentence=Alternative ESP32 Webserver implementation for the ESP32, supporting HTTPS and HTTP. +maintainer=Jack Jansen +sentence=Alternative ESP32 Webserver implementation for the ESP32, supporting HTTPS and HTTP. Compatible with ESP-IDF 5.0 or later. paragraph=The library provides TLS support and simultaneous connections. It can be used to run an HTTP or HTTPS server, or both in parallel. The server's resources are defined through handler and middleware functions, giving an easy start to everyone who has worked with frameworks like Express or Servlets before. category=Communication -url=https://github.com/fhessel/esp32_https_server +url=https://github.com/jackjansen/esp32_idf5_https_server architectures=esp32 includes=HTTPSServer.hpp,HTTPRequest.hpp,HTTPResponse.hpp diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..21146c3 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,45 @@ +[platformio] + + +[env] +framework = arduino +monitor_speed = 115200 +upload_speed = 460800 +build_type = debug +monitor_filters = esp32_exception_decoder +upload_port = /dev/cu.usbmodem11201 +build_src_filter = + +<*.cpp> + +<../examples/Websocket-Chat/*.cpp> + +[credentials] +wifi_ssids = + -DWIFI_SSID=\"${sysenv.WIFI_SSID}\" + -DWIFI_PSK=\"${sysenv.WIFI_PASSWORD}\" + +[env:custom-server] +;platform = espressif32@6.7.0 ; works fine with https + +; development fails to compile: +platform = https://github.com/pioarduino/platform-espressif32.git#develop +; stable: +;platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip + +; board = m5stack-cores3 +board = esp32-s3-devkitc-1-32MB-8MB + +upload_protocol = esptool +debug_tool = esp-builtin +debug_init_break = tbreak app_main +debug_speed = 10000 +build_flags = + -Isrc + -ggdb3 -O0 + -DCORE_DEBUG_LEVEL=5 + ${credentials.wifi_ssids} + -Dmbedtls_sha1_ret=mbedtls_sha1 +lib_deps = + ; https://github.com/mlesniew/PicoWebsocket.git + ; m5stack/M5Unified@0.1.16 + + diff --git a/src/ConnectionContext.hpp b/src/ConnectionContext.hpp index da88964..6778cd7 100644 --- a/src/ConnectionContext.hpp +++ b/src/ConnectionContext.hpp @@ -5,9 +5,9 @@ #include // Required for SSL -#include "openssl/ssl.h" -#undef read - +//#include "openssl/ssl.h" +//#undef read +#include namespace httpsserver { class WebsocketHandler; diff --git a/src/HTTPConnection.cpp b/src/HTTPConnection.cpp index 0ab739c..47ce9a2 100644 --- a/src/HTTPConnection.cpp +++ b/src/HTTPConnection.cpp @@ -1,5 +1,6 @@ #include "HTTPConnection.hpp" - +#include "mbedtls/base64.h" +#include "mbedtls/sha1.h" namespace httpsserver { HTTPConnection::HTTPConnection(ResourceResolver * resResolver): @@ -664,7 +665,7 @@ void handleWebsocketHandshake(HTTPRequest * req, HTTPResponse * res) { std::string websocketKeyResponseHash(std::string const &key) { std::string newKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; uint8_t shaData[HTTPS_SHA1_LENGTH]; - esp_sha(SHA1, (uint8_t*)newKey.data(), newKey.length(), shaData); + mbedtls_sha1((uint8_t*)newKey.data(), newKey.length(), shaData); // Get output size required for base64 representation size_t b64BufferSize = 0; diff --git a/src/HTTPConnection.hpp b/src/HTTPConnection.hpp index fb15d7a..f3e7695 100644 --- a/src/HTTPConnection.hpp +++ b/src/HTTPConnection.hpp @@ -6,7 +6,8 @@ #include #include -#include +#include +#include #include // Required for sockets diff --git a/src/HTTPResponse.hpp b/src/HTTPResponse.hpp index 7bd1758..2ff5c88 100644 --- a/src/HTTPResponse.hpp +++ b/src/HTTPResponse.hpp @@ -9,7 +9,8 @@ #undef write #include -#include +//#include +#include #include "util.hpp" diff --git a/src/HTTPSConnection.cpp b/src/HTTPSConnection.cpp index e0e3dd0..ff9ba5d 100644 --- a/src/HTTPSConnection.cpp +++ b/src/HTTPSConnection.cpp @@ -5,7 +5,7 @@ namespace httpsserver { HTTPSConnection::HTTPSConnection(ResourceResolver * resResolver): HTTPConnection(resResolver) { - _ssl = NULL; + _ssl = esp_tls_init(); } HTTPSConnection::~HTTPSConnection() { @@ -22,42 +22,32 @@ bool HTTPSConnection::isSecure() { * * The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance. */ -int HTTPSConnection::initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeaders *defaultHeaders) { +int HTTPSConnection::initialize(int serverSocketID, esp_tls_cfg_server_t * cfgSrv, HTTPHeaders *defaultHeaders) { if (_connectionState == STATE_UNDEFINED) { // Let the base class connect the plain tcp socket int resSocket = HTTPConnection::initialize(serverSocketID, defaultHeaders); - + HTTPS_LOGI("Cert len:%d, apn:%s\n",cfgSrv->servercert_bytes,cfgSrv->alpn_protos[0]); // Build up SSL Connection context if the socket has been created successfully if (resSocket >= 0) { - - _ssl = SSL_new(sslCtx); - - if (_ssl) { + int res=esp_tls_server_session_create(cfgSrv,resSocket,_ssl); + if (0==res) { + esp_tls_cfg_server_session_tickets_init(cfgSrv); + _cfg = cfgSrv; // Bind SSL to the socket - int success = SSL_set_fd(_ssl, resSocket); - if (success) { - - // Perform the handshake - success = SSL_accept(_ssl); - if (success) { + if (ESP_OK == esp_tls_get_conn_sockfd(_ssl,&resSocket)) { return resSocket; - } else { - HTTPS_LOGE("SSL_accept failed. Aborting handshake. FID=%d", resSocket); - } } else { - HTTPS_LOGE("SSL_set_fd failed. Aborting handshake. FID=%d", resSocket); + HTTPS_LOGE("SSL_accept failed. Aborting handshake. FID=%d", resSocket); } } else { - HTTPS_LOGE("SSL_new failed. Aborting handshake. FID=%d", resSocket); + HTTPS_LOGE("SSL_new failed. Aborting handshake. Error=%d", res); } } else { HTTPS_LOGE("Could not accept() new connection. FID=%d", resSocket); } - _connectionState = STATE_ERROR; _clientState = CSTATE_ACTIVE; - // This will only be called if the connection could not be established and cleanup // variables like _ssl etc. closeConnection(); @@ -84,18 +74,10 @@ void HTTPSConnection::closeConnection() { // Try to tear down SSL while we are in the _shutdownTS timeout period or if an error occurred if (_ssl) { - if(_connectionState == STATE_ERROR || SSL_shutdown(_ssl) == 0) { - // SSL_shutdown will return 1 as soon as the client answered with close notify - // This means we are safe to close the socket - SSL_free(_ssl); - _ssl = NULL; - } else if (_shutdownTS + HTTPS_SHUTDOWN_TIMEOUT < millis()) { - // The timeout has been hit, we force SSL shutdown now by freeing the context - SSL_free(_ssl); - _ssl = NULL; - HTTPS_LOGW("SSL_shutdown did not receive close notification from the client"); - _connectionState = STATE_ERROR; - } + esp_tls_cfg_server_session_tickets_free(_cfg); + esp_tls_server_session_delete(_ssl); + _ssl = NULL; + _connectionState = STATE_ERROR; } // If SSL has been brought down, close the socket @@ -105,19 +87,19 @@ void HTTPSConnection::closeConnection() { } size_t HTTPSConnection::writeBuffer(byte* buffer, size_t length) { - return SSL_write(_ssl, buffer, length); + return esp_tls_conn_write(_ssl,buffer,length);// SSL_write(_ssl, buffer, length); } size_t HTTPSConnection::readBytesToBuffer(byte* buffer, size_t length) { - return SSL_read(_ssl, buffer, length); + return esp_tls_conn_read(_ssl, buffer, length); } size_t HTTPSConnection::pendingByteCount() { - return SSL_pending(_ssl); + return esp_tls_get_bytes_avail(_ssl); } bool HTTPSConnection::canReadData() { - return HTTPConnection::canReadData() || (SSL_pending(_ssl) > 0); + return HTTPConnection::canReadData() || (esp_tls_get_bytes_avail(_ssl) > 0); } } /* namespace httpsserver */ diff --git a/src/HTTPSConnection.hpp b/src/HTTPSConnection.hpp index 8adbce5..6b0efa0 100644 --- a/src/HTTPSConnection.hpp +++ b/src/HTTPSConnection.hpp @@ -6,8 +6,9 @@ #include // Required for SSL -#include "openssl/ssl.h" -#undef read +//#include "openssl/ssl.h" +//#undef read +#include // Required for sockets #include "lwip/netdb.h" @@ -34,7 +35,7 @@ class HTTPSConnection : public HTTPConnection { HTTPSConnection(ResourceResolver * resResolver); virtual ~HTTPSConnection(); - virtual int initialize(int serverSocketID, SSL_CTX * sslCtx, HTTPHeaders *defaultHeaders); + virtual int initialize(int serverSocketID,esp_tls_cfg_server_t * cfgSrv, HTTPHeaders *defaultHeaders); virtual void closeConnection(); virtual bool isSecure(); @@ -49,8 +50,8 @@ class HTTPSConnection : public HTTPConnection { private: // SSL context for this connection - SSL * _ssl; - + esp_tls_t * _ssl; + esp_tls_cfg_server_t * _cfg; }; } /* namespace httpsserver */ diff --git a/src/HTTPSServer.cpp b/src/HTTPSServer.cpp index 4d8352d..249e5ce 100644 --- a/src/HTTPSServer.cpp +++ b/src/HTTPSServer.cpp @@ -2,17 +2,24 @@ namespace httpsserver { +constexpr const char * alpn_protos[] = { "http/1.1", NULL } ; HTTPSServer::HTTPSServer(SSLCert * cert, const uint16_t port, const uint8_t maxConnections, const in_addr_t bindAddress): HTTPServer(port, maxConnections, bindAddress), _cert(cert) { - // Configure runtime data - _sslctx = NULL; + _cfg = new esp_tls_cfg_server(); + _cfg->alpn_protos = (const char **)alpn_protos; + _cfg->cacert_buf = NULL; + _cfg->cacert_bytes = 0; + _cfg->servercert_buf =cert->getCertData(); + _cfg->servercert_bytes = cert->getCertLength(); + _cfg->serverkey_buf= cert->getPKData(); + _cfg->serverkey_bytes= cert->getPKLength(); } HTTPSServer::~HTTPSServer() { - + free(_cfg); } /** @@ -20,24 +27,15 @@ HTTPSServer::~HTTPSServer() { */ uint8_t HTTPSServer::setupSocket() { if (!isRunning()) { - if (!setupSSLCTX()) { - Serial.println("setupSSLCTX failed"); - return 0; - } - - if (!setupCert()) { - Serial.println("setupCert failed"); - SSL_CTX_free(_sslctx); - _sslctx = NULL; - return 0; - } + _cfg->servercert_buf= _cert->getCertData(); + _cfg->servercert_bytes = _cert->getCertLength(); + _cfg->serverkey_buf= _cert->getPKData(); + _cfg->serverkey_bytes= _cert->getPKLength(); if (HTTPServer::setupSocket()) { return 1; } else { Serial.println("setupSockets failed"); - SSL_CTX_free(_sslctx); - _sslctx = NULL; return 0; } } else { @@ -49,30 +47,12 @@ void HTTPSServer::teardownSocket() { HTTPServer::teardownSocket(); - // Tear down the SSL context - SSL_CTX_free(_sslctx); - _sslctx = NULL; } int HTTPSServer::createConnection(int idx) { HTTPSConnection * newConnection = new HTTPSConnection(this); _connections[idx] = newConnection; - return newConnection->initialize(_socket, _sslctx, &_defaultHeaders); -} - -/** - * This method configures the ssl context that is used for the server - */ -uint8_t HTTPSServer::setupSSLCTX() { - _sslctx = SSL_CTX_new(TLSv1_2_server_method()); - if (_sslctx) { - // Set SSL Timeout to 5 minutes - SSL_CTX_set_timeout(_sslctx, 300); - return 1; - } else { - _sslctx = NULL; - return 0; - } + return newConnection->initialize(_socket, _cfg , &_defaultHeaders); } /** @@ -81,22 +61,11 @@ uint8_t HTTPSServer::setupSSLCTX() { */ uint8_t HTTPSServer::setupCert() { // Configure the certificate first - uint8_t ret = SSL_CTX_use_certificate_ASN1( - _sslctx, - _cert->getCertLength(), - _cert->getCertData() - ); - - // Then set the private key accordingly - if (ret) { - ret = SSL_CTX_use_RSAPrivateKey_ASN1( - _sslctx, - _cert->getPKData(), - _cert->getPKLength() - ); - } - - return ret; + _cfg->servercert_buf= _cert->getCertData(); + _cfg->servercert_bytes = _cert->getCertLength(); + _cfg->serverkey_buf= _cert->getPKData(); + _cfg->serverkey_bytes= _cert->getPKLength(); + return 1; } } /* namespace httpsserver */ diff --git a/src/HTTPSServer.hpp b/src/HTTPSServer.hpp index 68596bf..5e87430 100644 --- a/src/HTTPSServer.hpp +++ b/src/HTTPSServer.hpp @@ -8,8 +8,9 @@ #include // Required for SSL -#include "openssl/ssl.h" -#undef read +//#include "openssl/ssl.h" +#include +//#undef read // Internal includes #include "HTTPServer.hpp" @@ -31,20 +32,19 @@ class HTTPSServer : public HTTPServer { public: HTTPSServer(SSLCert * cert, const uint16_t portHTTPS = 443, const uint8_t maxConnections = 4, const in_addr_t bindAddress = 0); virtual ~HTTPSServer(); - + virtual esp_tls_cfg_server_t *getConfig() {return _cfg;} private: // Static configuration. Port, keys, etc. ==================== // Certificate that should be used (includes private key) SSLCert * _cert; //// Runtime data ============================================ - SSL_CTX * _sslctx; + esp_tls_cfg_server_t * _cfg; // Status of the server: Are we running, or not? // Setup functions virtual uint8_t setupSocket(); virtual void teardownSocket(); - uint8_t setupSSLCTX(); uint8_t setupCert(); // Helper functions diff --git a/src/SSLCert.cpp b/src/SSLCert.cpp index 3df7073..fe608fd 100644 --- a/src/SSLCert.cpp +++ b/src/SSLCert.cpp @@ -3,306 +3,321 @@ namespace httpsserver { SSLCert::SSLCert(unsigned char * certData, uint16_t certLength, unsigned char * pkData, uint16_t pkLength): - _certLength(certLength), - _certData(certData), - _pkLength(pkLength), - _pkData(pkData) { + _certLength(certLength), + _certData(certData), + _pkLength(pkLength), + _pkData(pkData) { } SSLCert::~SSLCert() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } uint16_t SSLCert::getCertLength() { - return _certLength; + return _certLength; } uint16_t SSLCert::getPKLength() { - return _pkLength; + return _pkLength; } unsigned char * SSLCert::getCertData() { - return _certData; + return _certData; } unsigned char * SSLCert::getPKData() { - return _pkData; + return _pkData; } void SSLCert::setPK(unsigned char * pkData, uint16_t length) { - _pkData = pkData; - _pkLength = length; + _pkData = pkData; + _pkLength = length; } void SSLCert::setCert(unsigned char * certData, uint16_t length) { - _certData = certData; - _certLength = length; + _certData = certData; + _certLength = length; } void SSLCert::clear() { - for(uint16_t i = 0; i < _certLength; i++) _certData[i]=0; - delete _certData; - _certLength = 0; + for(uint16_t i = 0; i < _certLength; i++) _certData[i]=0; + delete _certData; + _certLength = 0; - for(uint16_t i = 0; i < _pkLength; i++) _pkData[i] = 0; - delete _pkData; - _pkLength = 0; + for(uint16_t i = 0; i < _pkLength; i++) _pkData[i] = 0; + delete _pkData; + _pkLength = 0; } #ifndef HTTPS_DISABLE_SELFSIGNING /** * Function to create the key for a self-signed certificate. - * + * * Writes private key as DER in certCtx - * + * * Based on programs/pkey/gen_key.c */ static int gen_key(SSLCert &certCtx, SSLKeySize keySize) { - // Initialize the entropy source - mbedtls_entropy_context entropy; - mbedtls_entropy_init( &entropy ); - - // Initialize the RNG - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ctr_drbg_init( &ctr_drbg ); - int rngRes = mbedtls_ctr_drbg_seed( - &ctr_drbg, mbedtls_entropy_func, &entropy, - NULL, 0 - ); - if (rngRes != 0) { - mbedtls_entropy_free( &entropy ); - return HTTPS_SERVER_ERROR_KEYGEN_RNG; - } - - // Initialize the private key - mbedtls_pk_context key; - mbedtls_pk_init( &key ); - int resPkSetup = mbedtls_pk_setup( &key, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ); - if ( resPkSetup != 0) { - mbedtls_ctr_drbg_free( &ctr_drbg ); - mbedtls_entropy_free( &entropy ); - return HTTPS_SERVER_ERROR_KEYGEN_SETUP_PK; - } - - // Actual key generation - int resPkGen = mbedtls_rsa_gen_key( - mbedtls_pk_rsa( key ), - mbedtls_ctr_drbg_random, - &ctr_drbg, - keySize, - 65537 - ); - if ( resPkGen != 0) { - mbedtls_pk_free( &key ); + // Initialize the entropy source + mbedtls_entropy_context entropy; + mbedtls_entropy_init( &entropy ); + + // Initialize the RNG + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ctr_drbg_init( &ctr_drbg ); + int rngRes = mbedtls_ctr_drbg_seed( + &ctr_drbg, mbedtls_entropy_func, &entropy, + NULL, 0 + ); + if (rngRes != 0) { + mbedtls_entropy_free( &entropy ); + return HTTPS_SERVER_ERROR_KEYGEN_RNG; + } + + // Initialize the private key + mbedtls_pk_context key; + mbedtls_pk_init( &key ); + int resPkSetup = mbedtls_pk_setup( &key, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ); + if ( resPkSetup != 0) { + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + return HTTPS_SERVER_ERROR_KEYGEN_SETUP_PK; + } + + // Actual key generation + int resPkGen = mbedtls_rsa_gen_key( + mbedtls_pk_rsa( key ), + mbedtls_ctr_drbg_random, + &ctr_drbg, + keySize, + 65537 + ); + if ( resPkGen != 0) { + mbedtls_pk_free( &key ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + return HTTPS_SERVER_ERROR_KEYGEN_GEN_PK; + } + + // Free the entropy source and the RNG as they are no longer needed mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); - return HTTPS_SERVER_ERROR_KEYGEN_GEN_PK; - } - // Free the entropy source and the RNG as they are no longer needed - mbedtls_ctr_drbg_free( &ctr_drbg ); - mbedtls_entropy_free( &entropy ); - - // Allocate the space on the heap, as stack size is quite limited - unsigned char * output_buf = new unsigned char[4096]; - if (output_buf == NULL) { - mbedtls_pk_free( &key ); - return HTTPS_SERVER_ERROR_KEY_OUT_OF_MEM; - } - memset(output_buf, 0, 4096); - - // Write the key to the temporary buffer and determine its length - int resPkWrite = mbedtls_pk_write_key_der( &key, output_buf, 4096 ); - if (resPkWrite < 0) { - delete[] output_buf; - mbedtls_pk_free( &key ); - return HTTPS_SERVER_ERROR_KEY_WRITE_PK; - } - size_t pkLength = resPkWrite; - unsigned char *pkOffset = output_buf + sizeof(unsigned char) * 4096 - pkLength; - - // Copy the key into a new, fitting space on the heap - unsigned char * output_pk = new unsigned char[pkLength]; - if (output_pk == NULL) { + // Allocate the space on the heap, as stack size is quite limited + unsigned char * output_buf = new unsigned char[4096]; + if (output_buf == NULL) { + mbedtls_pk_free( &key ); + return HTTPS_SERVER_ERROR_KEY_OUT_OF_MEM; + } + memset(output_buf, 0, 4096); + + // Write the key to the temporary buffer and determine its length + int resPkWrite = mbedtls_pk_write_key_der( &key, output_buf, 4096 ); + if (resPkWrite < 0) { + delete[] output_buf; + mbedtls_pk_free( &key ); + return HTTPS_SERVER_ERROR_KEY_WRITE_PK; + } + size_t pkLength = resPkWrite; + unsigned char *pkOffset = output_buf + sizeof(unsigned char) * 4096 - pkLength; + + // Copy the key into a new, fitting space on the heap + unsigned char * output_pk = new unsigned char[pkLength]; + if (output_pk == NULL) { + delete[] output_buf; + mbedtls_pk_free( &key ); + return HTTPS_SERVER_ERROR_KEY_WRITE_PK; + } + memcpy(output_pk, pkOffset, pkLength); + + // Clean up the temporary buffer and clear the key context delete[] output_buf; mbedtls_pk_free( &key ); - return HTTPS_SERVER_ERROR_KEY_WRITE_PK; - } - memcpy(output_pk, pkOffset, pkLength); - - // Clean up the temporary buffer and clear the key context - delete[] output_buf; - mbedtls_pk_free( &key ); - // Set the private key in the context - certCtx.setPK(output_pk, pkLength); + // Set the private key in the context + certCtx.setPK(output_pk, pkLength); - return 0; + return 0; } /** * Function to generate the X509 certificate data for a private key - * + * * Writes certificate in certCtx * * Based on programs/x509/cert_write.c */ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom, std::string validityTo) { - int funcRes = 0; - int stepRes = 0; - - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_pk_context key; - mbedtls_x509write_cert crt; - mbedtls_mpi serial; - unsigned char * primary_buffer; - unsigned char *certOffset; - unsigned char * output_buffer; - size_t certLength; - - // Make a C-friendly version of the distinguished name - char dn_cstr[dn.length()+1]; - strcpy(dn_cstr, dn.c_str()); - - // Initialize the entropy source - mbedtls_entropy_init( &entropy ); - - // Initialize the RNG - mbedtls_ctr_drbg_init( &ctr_drbg ); - stepRes = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0 ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_RNG; - goto error_after_entropy; - } - - mbedtls_pk_init( &key ); - stepRes = mbedtls_pk_parse_key( &key, certCtx.getPKData(), certCtx.getPKLength(), NULL, 0 ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_READKEY; - goto error_after_key; - } - - // Start configuring the certificate - mbedtls_x509write_crt_init( &crt ); - // Set version and hash algorithm - mbedtls_x509write_crt_set_version( &crt, MBEDTLS_X509_CRT_VERSION_3 ); - mbedtls_x509write_crt_set_md_alg( &crt, MBEDTLS_MD_SHA256 ); - - // Set the keys (same key as we self-sign) - mbedtls_x509write_crt_set_subject_key( &crt, &key ); - mbedtls_x509write_crt_set_issuer_key( &crt, &key ); - - // Set issuer and subject (same, as we self-sign) - stepRes = mbedtls_x509write_crt_set_subject_name( &crt, dn_cstr ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_NAME; - goto error_after_cert; - } - stepRes = mbedtls_x509write_crt_set_issuer_name( &crt, dn_cstr ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_NAME; - goto error_after_cert; - } - - // Set the validity of the certificate. At the moment, it's fixed from 2019 to end of 2029. - stepRes = mbedtls_x509write_crt_set_validity( &crt, validityFrom.c_str(), validityTo.c_str()); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_VALIDITY; - goto error_after_cert; - } - - // Make this a CA certificate - stepRes = mbedtls_x509write_crt_set_basic_constraints( &crt, 1, 0 ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_VALIDITY; - goto error_after_cert; - } - - // Initialize the serial number - mbedtls_mpi_init( &serial ); - stepRes = mbedtls_mpi_read_string( &serial, 10, "1" ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_SERIAL; - goto error_after_cert_serial; - } - stepRes = mbedtls_x509write_crt_set_serial( &crt, &serial ); - if (stepRes != 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_SERIAL; - goto error_after_cert_serial; - } - - // Create buffer to write the certificate - primary_buffer = new unsigned char[4096]; - if (primary_buffer == NULL) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_OUT_OF_MEM; - goto error_after_cert_serial; - } - - // Write the actual certificate - stepRes = mbedtls_x509write_crt_der(&crt, primary_buffer, 4096, mbedtls_ctr_drbg_random, &ctr_drbg ); - if (stepRes < 0) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_WRITE; - goto error_after_primary_buffer; - } - - // Create a matching buffer - certLength = stepRes; - certOffset = primary_buffer + sizeof(unsigned char) * 4096 - certLength; - - // Copy the cert into a new, fitting space on the heap - output_buffer = new unsigned char[certLength]; - if (output_buffer == NULL) { - funcRes = HTTPS_SERVER_ERROR_CERTGEN_OUT_OF_MEM; - goto error_after_primary_buffer; - } - memcpy(output_buffer, certOffset, certLength); - - // Configure the cert in the context - certCtx.setCert(output_buffer, certLength); - - // Run through the cleanup process + int funcRes = 0; + int stepRes = 0; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_pk_context key; + mbedtls_x509write_cert crt; +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + const char *serial = "peer"; +#else + mbedtls_mpi serial; +#endif + + unsigned char * primary_buffer; + unsigned char *certOffset; + unsigned char * output_buffer; + size_t certLength; + + // Make a C-friendly version of the distinguished name + char dn_cstr[dn.length()+1]; + strcpy(dn_cstr, dn.c_str()); + + // Initialize the entropy source + mbedtls_entropy_init( &entropy ); + + // Initialize the RNG + mbedtls_ctr_drbg_init( &ctr_drbg ); + stepRes = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0 ); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_RNG; + goto error_after_entropy; + } +#if MBEDTLS_VERSION_NUMBER < 0x03040000 + mbedtls_pk_init( &key ); + stepRes = mbedtls_pk_parse_key( &key, certCtx.getPKData(), certCtx.getPKLength(), NULL, 0 ); +#else + stepRes = mbedtls_pk_parse_key( &key, + certCtx.getPKData(), + certCtx.getPKLength(), + NULL, 0, NULL, NULL); +#endif + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_READKEY; + goto error_after_key; + } + // Start configuring the certificate + mbedtls_x509write_crt_init( &crt ); + // Set version and hash algorithm + mbedtls_x509write_crt_set_version( &crt, MBEDTLS_X509_CRT_VERSION_3 ); + mbedtls_x509write_crt_set_md_alg( &crt, MBEDTLS_MD_SHA256 ); + + // Set the keys (same key as we self-sign) + mbedtls_x509write_crt_set_subject_key( &crt, &key ); + mbedtls_x509write_crt_set_issuer_key( &crt, &key ); + + // Set issuer and subject (same, as we self-sign) + stepRes = mbedtls_x509write_crt_set_subject_name( &crt, dn_cstr ); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_NAME; + goto error_after_cert; + } + stepRes = mbedtls_x509write_crt_set_issuer_name( &crt, dn_cstr ); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_NAME; + goto error_after_cert; + } + + // Set the validity of the certificate. At the moment, it's fixed from 2019 to end of 2029. + stepRes = mbedtls_x509write_crt_set_validity( &crt, validityFrom.c_str(), validityTo.c_str()); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_VALIDITY; + goto error_after_cert; + } + + // Make this a CA certificate + stepRes = mbedtls_x509write_crt_set_basic_constraints( &crt, 1, 0 ); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_VALIDITY; + goto error_after_cert; + } + +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + mbedtls_x509write_crt_set_serial_raw(&crt, (unsigned char *) serial, strlen(serial)); +#else + // generate random serial number + mbedtls_mpi_init( &serial ); + stepRes = mbedtls_mpi_fill_random( &serial, 10, mbedtls_ctr_drbg_random, &ctr_drbg ); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_SERIAL; + goto error_after_cert_serial; + } + stepRes = mbedtls_x509write_crt_set_serial( &crt, &serial ); + if (stepRes != 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_SERIAL; + goto error_after_cert_serial; + } +#endif + // Create buffer to write the certificate + primary_buffer = new unsigned char[4096]; + if (primary_buffer == NULL) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_OUT_OF_MEM; + goto error_after_cert_serial; + } + + // Write the actual certificate + stepRes = mbedtls_x509write_crt_der(&crt, primary_buffer, 4096, mbedtls_ctr_drbg_random, &ctr_drbg ); + if (stepRes < 0) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_WRITE; + goto error_after_primary_buffer; + } + + // Create a matching buffer + certLength = stepRes; + certOffset = primary_buffer + sizeof(unsigned char) * 4096 - certLength; + + // Copy the cert into a new, fitting space on the heap + output_buffer = new unsigned char[certLength]; + if (output_buffer == NULL) { + funcRes = HTTPS_SERVER_ERROR_CERTGEN_OUT_OF_MEM; + goto error_after_primary_buffer; + } + memcpy(output_buffer, certOffset, certLength); + + // Configure the cert in the context + certCtx.setCert(output_buffer, certLength); + + // Run through the cleanup process error_after_primary_buffer: - delete[] primary_buffer; + delete[] primary_buffer; error_after_cert_serial: - mbedtls_mpi_free( &serial ); +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + mbedtls_mpi_free( &serial ); +#endif error_after_cert: - mbedtls_x509write_crt_free( &crt ); + mbedtls_x509write_crt_free( &crt ); error_after_key: - mbedtls_pk_free(&key); + mbedtls_pk_free(&key); error_after_entropy: - mbedtls_ctr_drbg_free( &ctr_drbg ); - mbedtls_entropy_free( &entropy ); - return funcRes; + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + return funcRes; } int createSelfSignedCert(SSLCert &certCtx, SSLKeySize keySize, std::string dn, std::string validFrom, std::string validUntil) { - // Add the private key - int keyRes = gen_key(certCtx, keySize); - if (keyRes != 0) { - // Key-generation failed, return the failure code - return keyRes; - } - - // Add the self-signed certificate - int certRes = cert_write(certCtx, dn, validFrom, validUntil); - if (certRes != 0) { - // Cert writing failed, reset the pk and return failure code - certCtx.setPK(NULL, 0); - return certRes; - } - - // If all went well, return 0 - return 0; + // Add the private key + int keyRes = gen_key(certCtx, keySize); + if (keyRes != 0) { + // Key-generation failed, return the failure code + return keyRes; + } + + // Add the self-signed certificate + int certRes = cert_write(certCtx, dn, validFrom, validUntil); + if (certRes != 0) { + // Cert writing failed, reset the pk and return failure code + certCtx.setPK(NULL, 0); + return certRes; + } + + // If all went well, return 0 + return 0; } #endif // !HTTPS_DISABLE_SELFSIGNING diff --git a/src/WebsocketHandler.cpp b/src/WebsocketHandler.cpp index 5e4c1d1..c0c3cc9 100644 --- a/src/WebsocketHandler.cpp +++ b/src/WebsocketHandler.cpp @@ -1,5 +1,9 @@ #include "WebsocketHandler.hpp" +#ifndef TAG +static const char *TAG = "WebsocketHandler"; +#endif + namespace httpsserver { /**