diff --git a/components/esp_websocket_client/examples/target/README.md b/components/esp_websocket_client/examples/target/README.md index 56870ea129..4233ecfea8 100644 --- a/components/esp_websocket_client/examples/target/README.md +++ b/components/esp_websocket_client/examples/target/README.md @@ -13,6 +13,47 @@ This example can be executed on any ESP32 board, the only required interface is * Open the project configuration menu (`idf.py menuconfig`) * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. * Configure the websocket endpoint URI under "Example Configuration", if "WEBSOCKET_URI_FROM_STDIN" is selected then the example application will connect to the URI it reads from stdin (used for testing) +* In order to test websocket client example over the TLS please enable configurations `CONFIG_WS_OVER_TLS_MUTUAL_AUTH` or `CONFIG_WS_OVER_TLS_SERVER_AUTH` (Needs only for python script executation over the TLS) + +### Server Certificate Verification + +* If you enable mutual authentification `CONFIG_WS_OVER_TLS_MUTUAL_AUTH=y`, you need to set a valid certificates for the server and client +* If you want to skip client certificate verification (only Server verification), enable `CONFIG_WS_OVER_TLS_SERVER_AUTH=y` only +* Example below demonstrates how to generate a new certificate for the server and client using the OpenSSL command line tool + +``` +Generate the CA's Private Key; +openssl genrsa -out ca_key.pem 2048 + +Create the CA's Certificate +openssl req -new -x509 -days 3650 -key ca_key.pem -out ca_cert.pem + +Generate the Server's Private Key +openssl genrsa -out server_key.pem 2048 + +Generate a Certificate Signing Request (CSR) for the Server +openssl req -new -key server_key.pem -out server_csr.pem + +Sign the Server's CSR with the CA's Certificate +openssl x509 -req -days 365 -in server_csr.pem -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial -out server_cert.pem + +Generate the Client's Private Key +openssl genrsa -out client_key.pem 2048 + +Generate a Certificate Signing Request (CSR) for the Client +openssl req -new -key client_key.pem -out client_csr.pem + +Sign the Client's CSR with the CA's Certificate +openssl x509 -req -days 365 -in client_csr.pem -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial -out client_cert.pem + +``` + +Expiry time and metadata fields can be adjusted in the invocation. + +Please see the openssl man pages (man openssl-req) for more details. + +It is **strongly recommended** to not reuse the example certificate in your application; +it is included only for demonstration. ### Build and Flash diff --git a/components/esp_websocket_client/examples/target/main/CMakeLists.txt b/components/esp_websocket_client/examples/target/main/CMakeLists.txt index bff26f1088..d5b1e0847a 100644 --- a/components/esp_websocket_client/examples/target/main/CMakeLists.txt +++ b/components/esp_websocket_client/examples/target/main/CMakeLists.txt @@ -1,2 +1,5 @@ idf_component_register(SRCS "websocket_example.c" - INCLUDE_DIRS ".") + INCLUDE_DIRS "." + EMBED_TXTFILES "certs/client_cert.pem" + EMBED_TXTFILES "certs/ca_cert.pem" + "certs/client_key.pem") diff --git a/components/esp_websocket_client/examples/target/main/Kconfig.projbuild b/components/esp_websocket_client/examples/target/main/Kconfig.projbuild index 49ad49effd..552dd7b83a 100644 --- a/components/esp_websocket_client/examples/target/main/Kconfig.projbuild +++ b/components/esp_websocket_client/examples/target/main/Kconfig.projbuild @@ -20,6 +20,20 @@ menu "Example Configuration" help URL of websocket endpoint this example connects to and sends echo + config WS_OVER_TLS_SERVER_AUTH + bool "Enable WebSocket over TLS with Server Certificate Verification Only" + default n + help + Enables WebSocket connections over TLS (WSS) with server certificate verification. + This setting mandates the client to verify the servers certificate, while the server + does not require client certificate verification. + + config WS_OVER_TLS_MUTUAL_AUTH + bool "Enable WebSocket over TLS with Server Client Mutual Authentification" + default n + help + Enables WebSocket connections over TLS (WSS) with server and client certificate verification. + if CONFIG_IDF_TARGET = "linux" config GCOV_ENABLED bool "Coverage analyzer" diff --git a/components/esp_websocket_client/examples/target/main/certs/ca_cert.pem b/components/esp_websocket_client/examples/target/main/certs/ca_cert.pem new file mode 100644 index 0000000000..4e461dd70a --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/ca_cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUe0LEmAMsFmKAg2DuDwXmcWXS5p8wDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDAyMTExNjI3MTlaFw0zNDAy +MDgxNjI3MTlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCvyjh5fJb8j50UzDCka7UqFLn5rdaixkyr++Pnkcqd +JL0URs5aG7m+PQHz8iFEQhcU4O8vkaeXK2V/vbFOBU0kNios0SUmzjcDTdmiJpVD ++yOM0Zvk9j5t9Y4WxL03FEqN9/kqw1XBJdJbVTLZgQ2eLWo0wMJwbL+M+EQJmk8A +6kDkEOZi0R1j8mAkjvqzWJcQMuVvQHTn/yOPYAeE8kC7lfUjNPR+QBu7e2j9q+zU +pomD7MiRnqtODRbikAyPnp+fjcrYQLxI2bNjJTIAErRSrECtEoqRAzJWZqTPpMEl +ArnuTADuSElqYsr6l+6ZJgodp6uUiwYQBHpizV2WCZD3AgMBAAGjUzBRMB0GA1Ud +DgQWBBSgvrq2q7WW4zdQMamqMmaSo/3YmTAfBgNVHSMEGDAWgBSgvrq2q7WW4zdQ +MamqMmaSo/3YmTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBO +wk8vaGfuuJ2jTUZ83t6io691KH2Wg3i/sQBAmFGI4cEccdIiiDeL5T2OW73uo9eY +HnFAcaoefDLGvgg/ABYLk+oZiKDw5Vxiu2hJehd1buVQ8PjMf13ZqtwVjwXaJuT8 +NU7pKo1LUyPDel6BbeOlCYa2LZPg2ZQhydkAz7jcfrh7h1QvMZmqPKlOIegZTtqx +vBnZKDyQtpkgWo+2NlBfPtDTNA2nKzicPL/YaMePYaUvcXrQQN0BURlbQyWlpW8m +Xoj/D8TMUSQiRtHDxSJhLbZDixx5lDwEeXcvB+pYBCUED7HFHKgo8KulIyiJgK1V +YZC2ha3nNU8uh90QPDnR +-----END CERTIFICATE----- diff --git a/components/esp_websocket_client/examples/target/main/certs/ca_key.pem b/components/esp_websocket_client/examples/target/main/certs/ca_key.pem new file mode 100644 index 0000000000..d09407b8d1 --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/ca_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvyjh5fJb8j50U +zDCka7UqFLn5rdaixkyr++PnkcqdJL0URs5aG7m+PQHz8iFEQhcU4O8vkaeXK2V/ +vbFOBU0kNios0SUmzjcDTdmiJpVD+yOM0Zvk9j5t9Y4WxL03FEqN9/kqw1XBJdJb +VTLZgQ2eLWo0wMJwbL+M+EQJmk8A6kDkEOZi0R1j8mAkjvqzWJcQMuVvQHTn/yOP +YAeE8kC7lfUjNPR+QBu7e2j9q+zUpomD7MiRnqtODRbikAyPnp+fjcrYQLxI2bNj +JTIAErRSrECtEoqRAzJWZqTPpMElArnuTADuSElqYsr6l+6ZJgodp6uUiwYQBHpi +zV2WCZD3AgMBAAECggEAIA0BwPy7Vq8kl78m+0N8E4EV63ULlkALiKvzgKwvQfmJ +0+GZDArUEeBzs7Oo5xYZuT/NvGGVKdXKusCuTChhSUHq7KLxYCLnGt4d2RepzWxD +rhAlmVhgR5Im5vXV/e3gLgRRVL+qqf2oXeipzche4EEthRLEINVjE2PMm+ebkfHW +QDts8CqZQgnvi24PKjVxgjaBMr4jK7myjCkrFZSWC4Hj5ezumsSXiGVDRgeRpaqu +crP+mB2q2skNeqrwe+7iFVORY254skD/FCp+VjCbO1BCUVcS/VVnzWunoAQmWWKM +buHUk9R/SMwhFdoNs6MDWAu4iknUf9ipSr8EirM54QKBgQDrLzIgkGaazqYogmjT +pX6GZwuHmPPJ8TLeD/Fq96//n4XUQAX1eI/+HAL5eiTSMt6QK4PNz4DXfkcJ4/IY +18MhMnqug0h9u3EJaosM6ecUBMQCzbfi9U9Vr7Fx/8V7loyTLqVpxp9Tr89zjSA8 +PdUuc2swvkhbmLclPReqS8G/kQKBgQC/WUQ2rETmtQXpUcXxvpcIwzSek4it7G5t +Q7T8QomggqpwjBjaeohIBaXRzXd4nZ4msUpWFote9AwPW3YZcwNSSY98P7g/OPBm +2FMiOPb/tXZQkClDspNLP2O98vLeAD+m0HwTGi61ulS98Za6kaH+HTg0LdtXMkTu +aJyKvWYUBwKBgQDc3MOshS92bl7oaB/dsutxeNABFYjMuvDUThCgLd9gpgTeYQm3 +jvNa5h98/lIZ/J+6sMLkwtvyg6pfBWxUHDwprug7fxrSyPbMqvvOstLJn/gb0enB +ADLy+z4fGt3wxF9b0VCSV29E/jRKBdyh9kd/ifC+I9R8AJzuIcNZsC9RoQKBgQCN +KLJMzvspYyPQQtYPB7Xt7eu0jEwJWmEAVDGA4ykacyp/SqrPChPdZeU1CCl5nnVc +P/AB4DHCw7Dd53ARSCqMGt4yH+OxKDUY+b8igPmeHGUC+8alPWix2zqel0qZgX9z +dVwCz47j22jGkyHJ0sO5bh7XR3kHM3tskVnic+SJIwKBgAjMSXyL1wuticxy7SqB +1JODo2hIj6mvfZqq/mXY8M3lm4jiKNcJSccd6x8ViYCBYPmMTIafvQI/QWK+8Sok +ERCbhO0dpKeKLpj1a5POQK7CL1uQEfFNhK8ttEoYgx+kVWOVYNY2INv7TBC5hiSM +yTSwhRBb2qDUihf1ulFHxk3X +-----END PRIVATE KEY----- diff --git a/components/esp_websocket_client/examples/target/main/certs/client_cert.pem b/components/esp_websocket_client/examples/target/main/certs/client_cert.pem new file mode 100644 index 0000000000..5de3d00485 --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/client_cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIUIF2nSdS4dXQzd77Uzk8h7ApClKEwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDAyMTExNjI4MzBaFw0yNTAy +MTAxNjI4MzBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQD4xRrf6yyNcwHKKZ03zReTcSaUieQyWL06uFLNhrBh +H7SZ/pmB3Y0ZNCVSIk0+Aw8XmJVYYOdaINXQS9LCS42csffQZCT7iJVdIPVQxiv8 +uvOJsdB/DM+Ui318vl0pv99snC9bsemCAa6IheWwvmCX/OgCfOiYBvNFOBDrIxpT +sJ0epd+vNSrKOzWFVMzArn3R/Kd8Qu8n5oAAZLzxnLN8MViKwr7/qATjlZioXrrL +mzmjq7NpPVXU+29XuenGazFq/87R3ukwGUOznBySNPbdz+eVyYDgVEkKtBvSRkGL +7TJ980l1tt5pxcrLT7/ildOsnqB4SGiLSvotWTJDRZQVAgMBAAGjQjBAMB0GA1Ud +DgQWBBSqPcUCOLmV1vU5kjFidC2TqPUsdjAfBgNVHSMEGDAWgBSgvrq2q7WW4zdQ +MamqMmaSo/3YmTANBgkqhkiG9w0BAQsFAAOCAQEAj75PgAxXvNz07q+cl3Y3XuN3 +/K6ix5B8iQDUg/sG22ZaKK0XmRWJSnfJay6emHJdHKuqHR3omjM5A7i7kiIatmbH +mN7dA17Y0yT+Sv6qR0dl+0iucF4tsDQmPZQCGKMpnNQoirTMAk4lcCcY69I6xHa6 +q9QhW/R5ueJkiHx+eg7ShH1KIqLsmvN9OM9+RTceC2qCKStPt9kldfnjmwvRzP6S +VgU5tUZJp10+bwV4yjoSsvO1xAXO4A4y6yU1RBSFyFZOaeKI24nIE9hT4uvc3wgb +mUuQfGAixj9a809YvgMquQAuVPi+iQe9b68qMgW5sil13xUeIzh7i/LkW2BN5Q== +-----END CERTIFICATE----- diff --git a/components/esp_websocket_client/examples/target/main/certs/client_key.pem b/components/esp_websocket_client/examples/target/main/certs/client_key.pem new file mode 100644 index 0000000000..7de8381592 --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/client_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD4xRrf6yyNcwHK +KZ03zReTcSaUieQyWL06uFLNhrBhH7SZ/pmB3Y0ZNCVSIk0+Aw8XmJVYYOdaINXQ +S9LCS42csffQZCT7iJVdIPVQxiv8uvOJsdB/DM+Ui318vl0pv99snC9bsemCAa6I +heWwvmCX/OgCfOiYBvNFOBDrIxpTsJ0epd+vNSrKOzWFVMzArn3R/Kd8Qu8n5oAA +ZLzxnLN8MViKwr7/qATjlZioXrrLmzmjq7NpPVXU+29XuenGazFq/87R3ukwGUOz +nBySNPbdz+eVyYDgVEkKtBvSRkGL7TJ980l1tt5pxcrLT7/ildOsnqB4SGiLSvot +WTJDRZQVAgMBAAECggEABwbNxqKw/wTrsj4fHAopLvstbDylSWwZIYjNEX5nik+k +SAxZYaWps37EO4qPKGqT7MZAUaZLDUH9gPbjTmxKHep8glJY7KAcxiUTSMcB9iu6 +i34AC2TdPXY09Lwp/X060BtszpKsyAUPsk4nq5pYjXJ1EkskBPHw3gM0SOjblRCg +bCS67jo+jj4lKKH2DzEYi6VFlVHhStuY0X94986nezsGfpAoDUvTPTQTfRHyO9bG +JCf9cFcpjl2vxGeDgoR177oITvQTztTR5L+zTk5plk/ILIHP9EjSmf8nCvt5+WHt +AplMox/piOn8eUK8rphDArD5iEHpfRPZQHmONXFy8QKBgQD8l9CunnOFWgdJS4jy ++EQDr3+6IXPJYwCcCF60rA2WgRbgt2ViPN+kEHaNI1MDEJdPsJTNBC7y0vKF09ga +zGgpKtPSD5boOCUnxpy8Cfobg01hZe9iYvl4HUIZSqAB7ZTtn2acXxeAw+f+dSEx +Fc5IKGvOIU2EKgw1Yu2AEPCq7wKBgQD8IBbHjU46+cldTiPNk4zfQ6xkbAgxttKS +7hZo3udpy/tvjdm2XBenrI4EDAIKhbWEvg7floN12cHfFZdTRlrdI1lnoeXFMQde +xEWfn+bpNLRGKY3HGrg2QvIkiClX1vevQOF63+eOlRdiC6xKosqkXrUIv/oY8ups +qs71hBDBOwKBgEXrTDOZ3sZR9mReiUkgWctfYA7IxcFAK2IFmxmN6rD3iLqpaWH5 +EbrbZ8WHuqnFhOzlJztc5hYHOGS9EDvSyx5iIYIrGI2tRPOusaIHbPkCrn/AdLQa +S43pI2vW0VXXSvs/vWqZk+rrz6MLDyYEMDafIcBMTaXA8eIxQSbLCaN3AoGBALq7 +nYOAoc9GT6B+jj/lJ3H4skbSSKNhb8aI9ioH5cdS38+4dOX+gTqbr7dJmX1nmJBP +H77zwDvZ4yAx4pk3w3aDhuUdYItTC81hetuF18UjVt2cSziLDqKJpMPv4QcA3QN8 +/0M9cEgHHoFsedfxiDqDNnvbjAVMbNm9DHmErdAfAoGAM2DlwjUnY4s6ebI52BRa +67FJshdOovr+5XpK3LuIOP/9d25lHElSW5KlRAP/PYd1gU0Aq21blJ8KrSg3Y83m +aEZQp7ga76uOEjDP2vY3jsMjyTP45ZvuKuf8t76FPKq1t0v2zNo4zfSScsnTKljh +u8E01zO1UDIhlc7tqf3r5NQ= +-----END PRIVATE KEY----- diff --git a/components/esp_websocket_client/examples/target/main/certs/server_cert.pem b/components/esp_websocket_client/examples/target/main/certs/server_cert.pem new file mode 100644 index 0000000000..af730d98f9 --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/server_cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIUIF2nSdS4dXQzd77Uzk8h7ApClKAwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDAyMTExNjI3NTFaFw0yNTAy +MTAxNjI3NTFaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC1BwoL3EQ0VCoN2T6dlOLbyzlLg42suEOWPk+Jx/yP +fMzp/Q1W0NWkNfqiHWi+8RAXiPeIzh1ex04rUKNY/+fZ7WJWiOiChm/HUWAYte14 +tic3/mkbw8+C1kkdQPGKsVUTMY5QhpBkRyKl6jaqzAEJI/QfqfMnLBxqnPpAYqmr +LCwjGPDmSjy0X3FeyZS6MNRkbgwd4zSz/rBVGAWTqrs8ipK2sMZlahhagmuqpVCd +EtPRf1WZDqVAXzI4LDbbX0FECfN8rHak7r1Oc/dT/AVAT0dq+F0vichLRsRRljkt +Sa7gmQNKfpZFd7vvqw6bxv3f/xP+rZb290kH1AvOgXFFAgMBAAGjQjBAMB0GA1Ud +DgQWBBSTcEPA+NXnhhSWQO02g2RWgeTJpTAfBgNVHSMEGDAWgBSgvrq2q7WW4zdQ +MamqMmaSo/3YmTANBgkqhkiG9w0BAQsFAAOCAQEAplo6DrvER6y+fMDCqVD1lnBz +tlwmjCr8sHQTYUi6prIvUQ3r5al+bCUxBD2K80sPjd7LDN4SVIma12qaLGbVUqDd +k4FGA6Man7dHdwVgcW6XFHcKGhdH+vMEHitccm7RsvDLxS33/kXo4hSgtQfbXHwD +7cgYF+6oN1JISOvMe0TuxFm8+48/++5KtaqYwPgRHgRbCq1ePowLEJN94qPv0EDb +ZTiVcK3cy+lZPpXOlhPtu+9GCcAnmC2Ho2QazPTgcdFO1aNqLp1CCRcg2l/QNLjr +QKw7rXoMSnnoIfAUdgkrzXVmo7qQ33GR8OW5Y+JfCBYx6L/jbvAkbWuxmgyX3Q== +-----END CERTIFICATE----- diff --git a/components/esp_websocket_client/examples/target/main/certs/server_csr.pem b/components/esp_websocket_client/examples/target/main/certs/server_csr.pem new file mode 100644 index 0000000000..2a35991294 --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/server_csr.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALUHCgvcRDRUKg3ZPp2U4tvLOUuDjay4Q5Y+T4nH +/I98zOn9DVbQ1aQ1+qIdaL7xEBeI94jOHV7HTitQo1j/59ntYlaI6IKGb8dRYBi1 +7Xi2Jzf+aRvDz4LWSR1A8YqxVRMxjlCGkGRHIqXqNqrMAQkj9B+p8ycsHGqc+kBi +qassLCMY8OZKPLRfcV7JlLow1GRuDB3jNLP+sFUYBZOquzyKkrawxmVqGFqCa6ql +UJ0S09F/VZkOpUBfMjgsNttfQUQJ83ysdqTuvU5z91P8BUBPR2r4XS+JyEtGxFGW +OS1JruCZA0p+lkV3u++rDpvG/d//E/6tlvb3SQfUC86BcUUCAwEAAaAAMA0GCSqG +SIb3DQEBCwUAA4IBAQAXpQCCptYKOAFi8eXjhtIPhowIXiaV/CdHSppfoev3IYB3 +K20Sc8iGbP3MKnG/2X7Js56rBpZ5ceF7tNHG6WMBw5VD+z1S5oNPxduV4N3wTXsy ++3P+eNCzE+0jii9N9WmMOTzMIchU1s+2cgQ8L4jgBd+NUL0EwyCvfDo/By34XCg1 +f/cxXSTSqu3pMGk+e1jgFPChwbNi51h8dJsgpjvuauzb5nIdrv2JuwiFXTPPCtjz +WoNFwBjEX5REt9/hqokadMPldMKu6GhG1V9EQMvMBhlykvOgmaKpiK1Bn2mAUt8F +Ixs9lEy1KmrafXVlJ6igiK2jXjDXuTEQVC+5QWcu +-----END CERTIFICATE REQUEST----- diff --git a/components/esp_websocket_client/examples/target/main/certs/server_key.pem b/components/esp_websocket_client/examples/target/main/certs/server_key.pem new file mode 100644 index 0000000000..3776b71a82 --- /dev/null +++ b/components/esp_websocket_client/examples/target/main/certs/server_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC1BwoL3EQ0VCoN +2T6dlOLbyzlLg42suEOWPk+Jx/yPfMzp/Q1W0NWkNfqiHWi+8RAXiPeIzh1ex04r +UKNY/+fZ7WJWiOiChm/HUWAYte14tic3/mkbw8+C1kkdQPGKsVUTMY5QhpBkRyKl +6jaqzAEJI/QfqfMnLBxqnPpAYqmrLCwjGPDmSjy0X3FeyZS6MNRkbgwd4zSz/rBV +GAWTqrs8ipK2sMZlahhagmuqpVCdEtPRf1WZDqVAXzI4LDbbX0FECfN8rHak7r1O +c/dT/AVAT0dq+F0vichLRsRRljktSa7gmQNKfpZFd7vvqw6bxv3f/xP+rZb290kH +1AvOgXFFAgMBAAECggEALPvuUasvIafGeYGCD0uHoiGaf7rVklWJqgSa5DyXdJqJ +Gx4gWfH0HOWy/eT7+fLSUl7dUBgT8VDqilXz+XJCDYPxO1qzGHhKv4dnr0xKEgSF +s2LbgKREZRlVutjADPxrDSVz3WvK5rhMklkks4WVPk26ZMHpI9NQzmdqwmQiEGAz +Jjs+LuysRaeJAma9MH/5JW4k6xN0V507pK5jJgyC2s+/1HMItSfY0EISc9nXKwKu +bypGGc0grgWkWkDh5CKhvaI7PctiUpF7A+qz5Pxp/igEw47BIxTi53z/UXwlShSy +gtjICiXwbcFssRvyvrefw8oSTYoODMnrlDDcYONY8wKBgQDbyqfSjJNbQBrBSaU1 +A1mWIGPxEM6f9FHY7dx8YVw27AdVMr4KyJWaPN0C7NStgD4ipVBkQjSmCXulmUWb +B9MXadUef9/a2GszMeO7wOXKhMVdKWP6DGFHFJ/W0YR977yGVd863S626BD/qyq2 +MuPHLzS5bcr5EVsB486hGMUBZwKBgQDS2ZJJvdOIxHbir0aaB6LxL8vJvxEFmRUk +5tnTfunHqN7P4myurCfcjJCT1nNhgnW1NQGwoPUjD3WT3nmDV8ub/tFKSTm7RycT +eGCrIAPkmLA7jGNzCkojCDPVIqQVY2Nx+ZE0bdC7YT06mMuEsF/Ccjq5I/+aJng4 +LIrFrL2wcwKBgQCEDi7nAi9HFCz/FRB92ZVp7eweWsrKsDC89a0TzitplEaTmfk0 +4W+BTDA+Ia1m0TaD+m9izaR0Xh48UOrRStI5rwytVodZJc7C46bAmBV4qG0snEHF +asrHukyO9TN1tyS+Ubnd1CbNHoGYG29+KPVSJ7q17pGVNChJ6mWrxQYY4QKBgQDF +uga3ZG5EqYibV6crttGUwC+pR6Ycy8vKSTooXbG57KDV7g3hV8whxSenm8mjvYXI +oqatDqQTduHaAx2Mj/5+kV2O/lBHUZhRZ+evUlyUOKO7lBGGxjVz2LNSwiOBcyzE +qzcCJaFCtxOGKddg3U1PuXNcP2fpFP5UH2EbsrxIBQKBgDaa8d1P4xA+n+eC8K9V +A3ovi1558isAyKbqGf8PW9rARAjFjmefPPlhBVYD4zvRQOPcaGYfupCjXoT+Vd29 +LrpCMXa4HajSzXqtuXoab4bGouKpXUKCyL5dynHnbuXCTETiopy6urvTpiem3199 +OE6HvS5pTjx2qxVjxRzkSapF +-----END PRIVATE KEY----- diff --git a/components/esp_websocket_client/examples/target/main/websocket_example.c b/components/esp_websocket_client/examples/target/main/websocket_example.c index 5984bb021e..875609e45a 100644 --- a/components/esp_websocket_client/examples/target/main/websocket_example.c +++ b/components/esp_websocket_client/examples/target/main/websocket_example.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -143,6 +143,20 @@ static void websocket_app_start(void) websocket_cfg.uri = CONFIG_WEBSOCKET_URI; #endif /* CONFIG_WEBSOCKET_URI_FROM_STDIN */ + extern const char cacert_start[] asm("_binary_ca_cert_pem_start"); // CA certificate + extern const char cert_start[] asm("_binary_client_cert_pem_start"); // Client certificate + extern const char cert_end[] asm("_binary_client_cert_pem_end"); + extern const char key_start[] asm("_binary_client_key_pem_start"); // Client private key + extern const char key_end[] asm("_binary_client_key_pem_end"); + + // Please note if you don't use server over TLS scheme (wss), the certificates are not required + websocket_cfg.cert_pem = cacert_start; + websocket_cfg.client_cert = cert_start; + websocket_cfg.client_cert_len = cert_end - cert_start; + websocket_cfg.client_key = key_start; + websocket_cfg.client_key_len = key_end - key_start; + websocket_cfg.skip_cert_common_name_check = true; + ESP_LOGI(TAG, "Connecting to %s...", websocket_cfg.uri); esp_websocket_client_handle_t client = esp_websocket_client_init(&websocket_cfg); diff --git a/components/esp_websocket_client/examples/target/pytest_websocket.py b/components/esp_websocket_client/examples/target/pytest_websocket.py index 9d6f315992..2d28d0180e 100644 --- a/components/esp_websocket_client/examples/target/pytest_websocket.py +++ b/components/esp_websocket_client/examples/target/pytest_websocket.py @@ -1,13 +1,16 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import json import random import re import socket +import ssl import string +import sys from threading import Event, Thread -from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket +from SimpleWebSocketServer import (SimpleSSLWebSocketServer, + SimpleWebSocketServer, WebSocket) def get_my_ip(): @@ -28,6 +31,7 @@ class WebsocketTestEcho(WebSocket): def handleMessage(self): self.sendMessage(self.data) print('Server sent: {}'.format(self.data)) + sys.stdout.flush() def handleConnected(self): print('Connection from: {}'.format(self.address)) @@ -44,12 +48,25 @@ def send_data(self, data): conn.sendMessage(data) def run(self): - self.server = SimpleWebSocketServer('', self.port, WebsocketTestEcho) + if self.use_tls is True: + ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + ssl_context.load_cert_chain(certfile='main/certs/server_cert.pem', keyfile='main/certs/server_key.pem') + if self.serv_verify is True: + ssl_context.load_verify_locations(cafile='main/certs/ca_cert.pem') + ssl_context.verify_mode = ssl.CERT_REQUIRED + else: + ssl_context.verify_mode = ssl.CERT_NONE + ssl_context.check_hostname = False + self.server = SimpleSSLWebSocketServer('', self.port, WebsocketTestEcho, ssl_context=ssl_context) + else: + self.server = SimpleWebSocketServer('', self.port, WebsocketTestEcho) while not self.exit_event.is_set(): self.server.serveonce() - def __init__(self, port): + def __init__(self, port, use_tls, verify): self.port = port + self.use_tls = use_tls + self.serv_verify = verify self.exit_event = Event() self.thread = Thread(target=self.run) self.thread.start() @@ -77,6 +94,7 @@ def test_echo(dut): for i in range(0, 5): dut.expect(re.compile(b'Received=hello (\\d)')) print('All echos received') + sys.stdout.flush() def test_close(dut): code = dut.expect( @@ -103,7 +121,8 @@ def test_json(dut, websocket): match = dut.expect( re.compile(b'Json=({[a-zA-Z0-9]*).*}')).group(0).decode()[5:] if match == str(data[0]): - print('Sent message and received message are equal') + print('Sent message and received message are equal \n') + sys.stdout.flush() else: raise ValueError( 'DUT received string do not match sent string, \nexpected: {}\nwith length {}\ @@ -126,7 +145,8 @@ def test_recv_long_msg(dut, websocket, msg_len, repeats): recv_msg += match if recv_msg == send_msg: - print('Sent message and received message are equal') + print('Sent message and received message are equal \n') + sys.stdout.flush() else: raise ValueError( 'DUT received string do not match sent string, \nexpected: {}\nwith length {}\ @@ -145,14 +165,27 @@ def test_fragmented_msg(dut): uri = dut.app.sdkconfig['WEBSOCKET_URI'] uri_from_stdin = False + if dut.app.sdkconfig.get('WS_OVER_TLS_MUTUAL_AUTH') is True: + use_tls = True + serv_verify = True + elif dut.app.sdkconfig.get('WS_OVER_TLS_SERVER_AUTH') is True: + use_tls = True + serv_verify = False + else: + use_tls = False + serv_verify = False + except Exception: print('ENV_TEST_FAILURE: Cannot find uri settings in sdkconfig') raise if uri_from_stdin: server_port = 8080 - with Websocket(server_port) as ws: - uri = 'ws://{}:{}'.format(get_my_ip(), server_port) + with Websocket(server_port, use_tls, serv_verify) as ws: + if use_tls is True: + uri = 'wss://{}:{}'.format(get_my_ip(), server_port) + else: + uri = 'ws://{}:{}'.format(get_my_ip(), server_port) print('DUT connecting to {}'.format(uri)) dut.expect('Please enter uri of websocket endpoint', timeout=30) dut.write(uri) diff --git a/components/esp_websocket_client/examples/target/sdkconfig.ci.tls_mutual_auth b/components/esp_websocket_client/examples/target/sdkconfig.ci.tls_mutual_auth new file mode 100644 index 0000000000..69bf6f8ee8 --- /dev/null +++ b/components/esp_websocket_client/examples/target/sdkconfig.ci.tls_mutual_auth @@ -0,0 +1,14 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_LINUX=n +CONFIG_WEBSOCKET_URI_FROM_STDIN=y +CONFIG_WEBSOCKET_URI_FROM_STRING=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_WS_OVER_TLS_MUTUAL_AUTH=y diff --git a/components/esp_websocket_client/examples/target/sdkconfig.ci.tls_servert_auth b/components/esp_websocket_client/examples/target/sdkconfig.ci.tls_servert_auth new file mode 100644 index 0000000000..e7e272fa4f --- /dev/null +++ b/components/esp_websocket_client/examples/target/sdkconfig.ci.tls_servert_auth @@ -0,0 +1,14 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_LINUX=n +CONFIG_WEBSOCKET_URI_FROM_STDIN=y +CONFIG_WEBSOCKET_URI_FROM_STRING=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_WS_OVER_TLS_SERVER_AUTH=y