Skip to content

Commit 651322e

Browse files
Jason2866me-no-devlucasssvaz
authored
3.0.0 Network Refactoring (espressif#8760)
* Create ESP_NetworkInterface class and have Ethernet extending it * Update CMakeLists.txt * Split networking from WiFi (H2 can now use Ethernet) Now all libs have been checked yet. More to do on WiFi side * Fix build errors * Guard WiFi classes and fix RMII ETH examples * Decouple network related libraries from WiFi * Fix examples and WiFiUpdate * Guard WiFiProv lib to compile only on WiFi chips * Add periman string for network and "fix" mdns on the first ETH * Revert back location of Client/Server/Udp in order to accept some PRs * Fix periman * Some fixes from merging master * Fix web server missing fs.h * Move Client, Server and Udp out of WiFi * More fixes * more fixes * Fix CMakekLists and rework lib menu dependencies * Fix CMake issues * move back WiFiClient to rebase with master * Update ETH_TLK110.ino * Move back WiFiClient * Update progress * Update WiFiGeneric.cpp * More fixes * Switch AP to the new interface * Cleanup * Rename AP methods * Add extra interface info for Printable * Rename IPv6 getters to clarify that they are returning LinkLocal address cc @sgryphon * Rename network classes cc @sgryphon * Update NetworkManager.h * Rename WiFi Server and UDP * Rename WiFiClient and WiFiClientSecure * Update CMakeLists.txt * Update on-push.sh * Rename Network library * Remove unnecessary guard * Get the correct interface MAC address for mDND Workstation service * Apply suggestions from code review --------- Co-authored-by: Me No Dev <[email protected]> Co-authored-by: Lucas Saavedra Vaz <[email protected]>
1 parent 5954dc7 commit 651322e

22 files changed

+2335
-0
lines changed
+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
NetworkClientSecure
2+
================
3+
4+
The NetworkClientSecure class implements support for secure connections using TLS (SSL).
5+
It inherits from NetworkClient and thus implements a superset of that class' interface.
6+
There are three ways to establish a secure connection using the NetworkClientSecure class:
7+
using a root certificate authority (CA) cert, using a root CA cert plus a client cert and key,
8+
and using a pre-shared key (PSK).
9+
10+
Using a root certificate authority cert
11+
---------------------------------------
12+
This method authenticates the server and negotiates an encrypted connection.
13+
It is the same functionality as implemented in your web browser when you connect to HTTPS sites.
14+
15+
If you are accessing your own server:
16+
- Generate a root certificate for your own certificate authority
17+
- Generate a cert & private key using your root certificate ("self-signed cert") for your server
18+
19+
If you are accessing a public server:
20+
- Obtain the cert of the public CA that signed that server's cert
21+
Then:
22+
- In NetworkClientSecure use setCACert (or the appropriate connect method) to set the root cert of your
23+
CA or of the public CA
24+
- When NetworkClientSecure connects to the target server it uses the CA cert to verify the certificate
25+
presented by the server, and then negotiates encryption for the connection
26+
27+
Please see the NetworkClientSecure example.
28+
29+
Using a bundle of root certificate authority certificates
30+
---------------------------------------------------------
31+
This method is similar to the single root certificate verfication above, but it uses a standard set of
32+
root certificates from Mozilla to authenticate against, while the previous method only accepts a single
33+
certificate for a given server. This allows the client to connect to all public SSL servers.
34+
35+
To use this feature in PlatformIO:
36+
1. create a certificate bundle as described in the document below, or obtain a pre-built one you trust:
37+
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_crt_bundle.html
38+
(gen_crt_bundle.py can be found in the /tools folder)
39+
a. note: the full bundle will take up around 64k of flash space, but has minimal RAM usage, as only
40+
the index of the certificates is kept in RAM
41+
2. Place the bundle under the file name "data/cert/x509_crt_bundle.bin" in your platformio project
42+
3. add "board_build.embed_files = data/cert/x509_crt_bundle.bin" in your platformio.ini
43+
4. add the following global declaration in your project:
44+
extern const uint8_t rootca_crt_bundle_start[] asm("_binary_data_cert_x509_crt_bundle_bin_start");
45+
5. before initiating the first SSL connection, call
46+
my_client.setCACertBundle(rootca_crt_bundle_start);
47+
48+
To use this feature in Arduino IDE:
49+
If the Arduino IDE added support for embedding files in the meantime, then follow the instructions above.
50+
If not, you have three choices:
51+
1. convert your project to PlatformIO
52+
2. create a makefile where you can add the idf_component_register() declaration to include the certificate bundle
53+
3. Store the bundle as a SPIFFS file, but then you have to load it into RAM in runtime and waste 64k of precious memory
54+
55+
Using a root CA cert and client cert/keys
56+
-----------------------------------------
57+
This method authenticates the server and additionally also authenticates
58+
the client to the server, then negotiates an encrypted connection.
59+
60+
- Follow steps above
61+
- Using your root CA generate cert/key for your client
62+
- Register the keys with the server you will be accessing so the server can authenticate your client
63+
- In NetworkClientSecure use setCACert (or the appropriate connect method) to set the root cert of your
64+
CA or of the public CA, this is used to authenticate the server
65+
- In NetworkClientSecure use setCertificate, and setPrivateKey (or the appropriate connect method) to
66+
set your client's cert & key, this will be used to authenticate your client to the server
67+
- When NetworkClientSecure connects to the target server it uses the CA cert to verify the certificate
68+
presented by the server, it will use the cert/key to authenticate your client to the server, and
69+
it will then negotiate encryption for the connection
70+
71+
Using Pre-Shared Keys (PSK)
72+
---------------------------
73+
74+
TLS supports authentication and encryption using a pre-shared key (i.e. a key that both client and
75+
server know) as an alternative to the public key cryptography commonly used on the web for HTTPS.
76+
PSK is starting to be used for MQTT, e.g. in mosquitto, to simplify the set-up and avoid having to
77+
go through the whole CA, cert, and private key process.
78+
79+
A pre-shared key is a binary string of up to 32 bytes and is commonly represented in hex form. In
80+
addition to the key, clients can also present an id and typically the server allows a different key
81+
to be associated with each client id. In effect this is very similar to username and password pairs,
82+
except that unlike a password the key is not directly transmitted to the server, thus a connection to a
83+
malicious server does not divulge the password. Plus the server is also authenticated to the client.
84+
85+
To use PSK:
86+
- Generate a random hex string (generating an MD5 or SHA for some file is one way to do this)
87+
- Come up with a string id for your client and configure your server to accept the id/key pair
88+
- In NetworkClientSecure use setPreSharedKey (or the appropriate connect method) to
89+
set the id/key combo
90+
- When NetworkClientSecure connects to the target server it uses the id/key combo to authenticate the
91+
server (it must prove that it has the key too), authenticate the client and then negotiate
92+
encryption for the connection
93+
94+
Please see the NetworkClientPSK example.
95+
96+
Specifying the ALPN Protocol
97+
----------------------------
98+
99+
Application-Layer Protocol Negotiation (ALPN) is a Transport Layer Security (TLS) extension that allows
100+
the application layer to negotiate which protocol should be performed over a secure connection in a manner
101+
that avoids additional round trips and which is independent of the application-layer protocols.
102+
103+
For example, this is used with AWS IoT Custom Authorizers where an MQTT client must set the ALPN protocol to ```mqtt```:
104+
105+
```
106+
const char *aws_protos[] = {"mqtt", NULL};
107+
...
108+
wiFiClient.setAlpnProtocols(aws_protos);
109+
```
110+
111+
Examples
112+
--------
113+
#### NetworkClientInsecure
114+
Demonstrates usage of insecure connection using `NetworkClientSecure::setInsecure()`
115+
#### NetworkClientPSK
116+
Wifi secure connection example for ESP32 using a pre-shared key (PSK)
117+
This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto.
118+
Running on TLS 1.2 using mbedTLS
119+
#### NetworkClientSecure
120+
Wifi secure connection example for ESP32
121+
Running on TLS 1.2 using mbedTLS
122+
#### NetworkClientSecureEnterprise
123+
This example demonstrates a secure connection to a WiFi network using WPA/WPA2 Enterprise (for example eduroam),
124+
and establishing a secure HTTPS connection with an external server (for example arduino.php5.sk) using the defined anonymous identity, user identity, and password.
125+
126+
.. note::
127+
This example is outdated and might not work. For more examples see [https://github.com/martinius96/ESP32-eduroam](https://github.com/martinius96/ESP32-eduroam)
128+
129+
#### NetworkClientShowPeerCredentials
130+
Example of a establishing a secure connection and then showing the fingerprint of the certificate.
131+
This can be useful in an IoT setting to know for sure that you are connecting to the right server.
132+
Especially in situations where you cannot hardcode a trusted root certificate for long
133+
periods of time (as they tend to get replaced more often than the lifecycle of IoT hardware).

libraries/NetworkClientSecure/examples/WiFiClientInsecure/.skip.esp32h2

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <NetworkClientSecure.h>
2+
#include <WiFi.h>
3+
4+
/* This is a very INSECURE approach.
5+
* If for some reason the secure, proper example NetworkClientSecure
6+
* does not work for you; then you may want to check the
7+
* NetworkClientTrustOnFirstUse example first. It is less secure than
8+
* NetworkClientSecure, but a lot better than this totally insecure
9+
* approach shown below.
10+
*/
11+
12+
const char* ssid = "your-ssid"; // your network SSID (name of wifi network)
13+
const char* password = "your-password"; // your network password
14+
15+
const char* server = "www.howsmyssl.com"; // Server URL
16+
17+
NetworkClientSecure client;
18+
19+
void setup() {
20+
//Initialize serial and wait for port to open:
21+
Serial.begin(115200);
22+
delay(100);
23+
24+
Serial.print("Attempting to connect to SSID: ");
25+
Serial.println(ssid);
26+
WiFi.begin(ssid, password);
27+
28+
// attempt to connect to Wifi network:
29+
while (WiFi.status() != WL_CONNECTED) {
30+
Serial.print(".");
31+
// wait 1 second for re-trying
32+
delay(1000);
33+
}
34+
35+
Serial.print("Connected to ");
36+
Serial.println(ssid);
37+
38+
Serial.println("\nStarting connection to server...");
39+
client.setInsecure();//skip verification
40+
if (!client.connect(server, 443))
41+
Serial.println("Connection failed!");
42+
else {
43+
Serial.println("Connected to server!");
44+
// Make a HTTP request:
45+
client.println("GET https://www.howsmyssl.com/a/check HTTP/1.0");
46+
client.println("Host: www.howsmyssl.com");
47+
client.println("Connection: close");
48+
client.println();
49+
50+
while (client.connected()) {
51+
String line = client.readStringUntil('\n');
52+
if (line == "\r") {
53+
Serial.println("headers received");
54+
break;
55+
}
56+
}
57+
// if there are incoming bytes available
58+
// from the server, read them and print them:
59+
while (client.available()) {
60+
char c = client.read();
61+
Serial.write(c);
62+
}
63+
64+
client.stop();
65+
}
66+
}
67+
68+
void loop() {
69+
// do nothing
70+
}

libraries/NetworkClientSecure/examples/WiFiClientPSK/.skip.esp32h2

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Wifi secure connection example for ESP32 using a pre-shared key (PSK)
3+
This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto.
4+
Running on TLS 1.2 using mbedTLS
5+
6+
To test run a test server using: openssl s_server -accept 8443 -psk 1a2b3c4d -nocert
7+
It will show the http request made, but there's no easy way to send a reply back...
8+
9+
2017 - Evandro Copercini - Apache 2.0 License.
10+
2018 - Adapted for PSK by Thorsten von Eicken
11+
*/
12+
13+
#include <NetworkClientSecure.h>
14+
#include <WiFi.h>
15+
16+
#if 0
17+
const char* ssid = "your-ssid"; // your network SSID (name of wifi network)
18+
const char* password = "your-password"; // your network password
19+
#else
20+
const char* ssid = "test"; // your network SSID (name of wifi network)
21+
const char* password = "securetest"; // your network password
22+
#endif
23+
24+
//const char* server = "server.local"; // Server hostname
25+
const IPAddress server = IPAddress(192, 168, 0, 14); // Server IP address
26+
const int port = 8443; // server's port (8883 for MQTT)
27+
28+
const char* pskIdent = "Client_identity"; // PSK identity (sometimes called key hint)
29+
const char* psKey = "1a2b3c4d"; // PSK Key (must be hex string without 0x)
30+
31+
NetworkClientSecure client;
32+
33+
void setup() {
34+
//Initialize serial and wait for port to open:
35+
Serial.begin(115200);
36+
delay(100);
37+
38+
Serial.print("Attempting to connect to SSID: ");
39+
Serial.println(ssid);
40+
WiFi.begin(ssid, password);
41+
42+
// attempt to connect to Wifi network:
43+
while (WiFi.status() != WL_CONNECTED) {
44+
Serial.print(".");
45+
// wait 1 second for re-trying
46+
delay(1000);
47+
}
48+
49+
Serial.print("Connected to ");
50+
Serial.println(ssid);
51+
52+
client.setPreSharedKey(pskIdent, psKey);
53+
54+
Serial.println("\nStarting connection to server...");
55+
if (!client.connect(server, port))
56+
Serial.println("Connection failed!");
57+
else {
58+
Serial.println("Connected to server!");
59+
// Make a HTTP request:
60+
client.println("GET /a/check HTTP/1.0");
61+
client.print("Host: ");
62+
client.println(server);
63+
client.println("Connection: close");
64+
client.println();
65+
66+
while (client.connected()) {
67+
String line = client.readStringUntil('\n');
68+
if (line == "\r") {
69+
Serial.println("headers received");
70+
break;
71+
}
72+
}
73+
// if there are incoming bytes available
74+
// from the server, read them and print them:
75+
while (client.available()) {
76+
char c = client.read();
77+
Serial.write(c);
78+
}
79+
80+
client.stop();
81+
}
82+
}
83+
84+
void loop() {
85+
// do nothing
86+
}

libraries/NetworkClientSecure/examples/WiFiClientSecure/.skip.esp32h2

Whitespace-only changes.

0 commit comments

Comments
 (0)