Skip to content

Add WPA2 Enterprise APIs and example #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions examples/WiFiWebClientWPA2Enterprise/WiFiWebClientWPA2Enterprise.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
Web client using WPA2 Enterprise connection

This sketch connects to a website (http://www.arduino.cc)
using the WiFi module.

This example is written for a network using WPA2 Enterprise encryption.

Circuit:
Board with NINA module (Arduino MKR WiFi 1010, MKR VIDOR 4000 and UNO WiFi Rev.2) with firmware > 1.2.4

created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
modified 14 Aug 2019
by Martino Facchin
*/


#include <SPI.h>
#include <WiFiNINA.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
int keyIndex = 0; // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
char server[] = "www.arduino.cc"; // name address for Arduino.cc (using DNS)

// Initialize the WiFi Client
WiFiClient client;

// WPA2 Enterprise usage:

// Certificates and credentials are stored in secret tab to avoid sharing them.
// For some networks (like eduroam) your configuration will simply look like
//
// #define SECRET_SSID "eduroam"
// #define SECRET_USERNAME "[email protected]"
// #define SECRET_PASS "yourpassword"
//
// Call WiFi.beginEnterprise(SECRET_SSID, SECRET_USERNAME, SECRET_PASS) and you should easily connect
//
// In case of more complicated networks (that require a certificate, for example) you can use
// WPA2Enterprise functions
// WPA2Enterprise.addCACertificate() , addClientCertificate(), addIdentity() ...
// and then call WiFi.begin() as usual.

void setup() {
// Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // Wait for serial port to connect. Needed for native USB port only
}

// Configure the wifi module to use provided WPA2 Enterprise parameters (if needed)
Serial.println("Configuring WPA2 Enterprise credentials");
WPA2Enterprise.addCACertificate(ca_pem);
WPA2Enterprise.addClientCertificate(client_crt, client_key);

// Check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// Don't continue
while (true);
}

String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}

// Attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA2 enterptise network (shows as an open network).
status = WiFi.beginEnterprise(ssid, SECRET_USERNAME, SECRET_PASSWORD);

// Wait 1 second for connection:
delay(1000);
}
Serial.println("Connected to wifi");
printWifiStatus();

Serial.println("\nStarting connection to server...");
// If you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /asciilogo.txt HTTP/1.1");
client.println("Host: www.arduino.cc");
client.println("Connection: close");
client.println();
}
}

void loop() {
// If there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
char c = client.read();
Serial.write(c);
}

// If the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();

// Do nothing forevermore:
while (true);
}
}


void printWifiStatus() {
// Print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// Print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// Print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
93 changes: 93 additions & 0 deletions examples/WiFiWebClientWPA2Enterprise/arduino_secrets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#define SECRET_SSID ""
#define SECRET_USERNAME ""
#define SECRET_PASSWORD ""

// This certificates are completely bogus, but your own should resemble this format
// For testing, generate them using the bootstrap script in freeradius-server/raddb repository, then
// * remove the password from client key with using this command
// openssl rsa -in client.key -out client2.key # default password is "whatever"
// * slim down client certificate by just keeping the snippet between BEGIN and END (must be smaller than 4Kbytes)

const char * ca_pem = "-----BEGIN CERTIFICATE-----\n"
"MIIE5DCCA8ygAwIBAgIJAM/ZGtauwvHrMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD\n"
"VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT\n"
"BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs\n"
"ZS5vcmcxJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X\n"
"DTE4MDQyNDIxMzQ0MloXDTE5MDQyNDIxMzQ0MlowgZMxCzAJBgNVBAYTAkZSMQ8w\n"
"DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh\n"
"bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9yZzEmMCQG\n"
"A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3\n"
"DQEBAQUAA4IBDwAwggEKAoIBAQDBM2wjdTRn0OmRadONV9EZPQyUxuo9iJ6DKHkt\n"
"rGEOd1gG4gNksrsF7gWcPdCWVCO49Xba1a16U/dyBPSuF7KHMO6Hx0OHZmJvCF1W\n"
"en8BPY9ClreYAobqnHIdQRIP8R5tpXA8qZ5aZlnD5dUB8XDka0NDNEXbvmbop6PP\n"
"OaGoNGsXzWN9mk2xQqHxYgoSHPER3QH2YCsKstgD87C/jTkHmtylv6j90PUhWTOm\n"
"oIbkQG0d1f4RNxcDdcRr18wOvk62CW2+phkWWRie/Vw5Lu1dA/bGzxFV64jX5J1+\n"
"ZZ5lyL87AE6bKtJjhLuqnPIarzenhmtCuGOsTTeFKgjlKLapAgMBAAGjggE3MIIB\n"
"MzAdBgNVHQ4EFgQUSsYRmVXei6Km4z5QPSYOvz7Zu00wgcgGA1UdIwSBwDCBvYAU\n"
"SsYRmVXei6Km4z5QPSYOvz7Zu02hgZmkgZYwgZMxCzAJBgNVBAYTAkZSMQ8wDQYD\n"
"VQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhhbXBs\n"
"ZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9yZzEmMCQGA1UE\n"
"AwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDP2RrWrsLx6zAPBgNV\n"
"HRMBAf8EBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93d3cuZXhhbXBs\n"
"ZS5vcmcvZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADggEBAFbOEusBzXfa\n"
"0qdTw3U98t58BUxYYzScKZNjgS/MYVEdS0OaMxYyqstp8BKr8YugEHUHGDJt9k37\n"
"yXGLVUeS+ST/Xy2UvOus7bLv0YYL26tQbBs5iDy9WJ3IBUtWhfqQW/ISpfma2uvN\n"
"kFfGCV0JkPa57oR1kj0OPkOBQSXPwTbbabUdQmB+d6IZi9ZTMGLv1ogq75X5eSJP\n"
"Qi6ql9nQF6TN24DIF8XJ/D6GJPbdmoMQ18VGoRlnz37Ee82ve9I5gvJquXZjOBd4\n"
"rK7p3mrSzzkiCdjB8ehpJygmgT1U/ufE1PopES8hSkCgvQ2EsNBIGYiJUFRJfeEM\n"
"kCCZqNTTmGE=\n"
"-----END CERTIFICATE-----";

const char * client_crt = "-----BEGIN CERTIFICATE-----\n"
"MIIEQTCCAymgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCRlIx\n"
"DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRQwEgYDVQQKDAtF\n"
"eGFtcGxlIEluYzEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5vcmcxJjAk\n"
"BgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE5MDgxMjE0\n"
"MTEyMVoXDTE5MTAxMTE0MTEyMVowdDELMAkGA1UEBhMCRlIxDzANBgNVBAgMBlJh\n"
"ZGl1czEUMBIGA1UECgwLRXhhbXBsZSBJbmMxFTATBgNVBAMMDEV4YW1wbGUgdXNl\n"
"cjEnMCUGCSqGSIb3DQEJARYYdXNlci5leGFtcGxlQGV4YW1wbGUub3JnMIIBIjAN\n"
"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtaiggI1w7wez/DjYM+F1RDUMa73J\n"
"07+XZM1OxQuRt8hbwh8wod1Bmu3iFtsSnzssygeek/9+Vd6gXqW5jBa4sMz0CQM1\n"
"PkIjBsgjPaKk98c2tyDYqA+nz0Wi9JOkAKPQwTTDijsAF3QfgcGvWZJngjHkeKoz\n"
"1BLJehDO4wOu1z3kB8CQGWQ0hZW2Sjt+qFqDTXt8Q0GF+nehqx7juHw/e6QDNiuH\n"
"Xmf0adJWUzFeMnQewUDD5R3EBLUiWzKbRFxoi0qs/tM1IUPQ0fASHcJMwZllCZpa\n"
"3B9nxAhLScR8RjDU0d0F+3hQGNKShJyvvR6dM2Qzie8H2yA7QrLdRX8XywIDAQAB\n"
"o4G+MIG7MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoGCCsGAQUF\n"
"BwMCMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93d3cuZXhhbXBsZS5jb20vZXhh\n"
"bXBsZV9jYS5jcmwwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v\n"
"d3d3LmV4YW1wbGUub3JnL29jc3AwGwYDVR0RBBQwEoEQdXNlckBleGFtcGxlLm9y\n"
"ZzANBgkqhkiG9w0BAQsFAAOCAQEAVC05K4XqjfjoTgQeB7FtjDUiuQedbNi3z3Sy\n"
"2qZVqgaYa+z9cijrL6Z7Z5BvM+JWUxfPjiXXF6M/j1QeyNLKtieDusO/yUaQTmSz\n"
"fyYbdXNlGBzsMLGMgp+xComZ5ZUQQwsmx8phagWqNlzAnQuLyyRshj+hOYjmysXs\n"
"2V6SUfRMEdgr57hRREHZBjJq/PQZL0Kw7BiXMYhMfFJfe1Z4LBYhRqAPDWVoPI1j\n"
"MNXM6X7R5zSNRbrj9biT4WNLBDooDW4Bzz1cimLock/nCY+TTj8Xoy/0szqkIdps\n"
"G1SM9dB7SdXDW6DewvRK28+9xe6HG4xsLtNNYFWqhPkF5S4BIg==\n"
"-----END CERTIFICATE-----";

const char * client_key = "-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEpAIBAAKCAQEAtaiggI1w7wez/DjYM+F1RDUMa73J07+XZM1OxQuRt8hbwh8w\n"
"od1Bmu3iFtsSnzssygeek/9+Vd6gXqW5jBa4sMz0CQM1PkIjBsgjPaKk98c2tyDY\n"
"qA+nz0Wi9JOkAKPQwTTDijsAF3QfgcGvWZJngjHkeKoz1BLJehDO4wOu1z3kB8CQ\n"
"GWQ0hZW2Sjt+qFqDTXt8Q0GF+nehqx7juHw/e6QDNiuHXmf0adJWUzFeMnQewUDD\n"
"5R3EBLUiWzKbRFxoi0qs/tM1IUPQ0fASHcJMwZllCZpa3B9nxAhLScR8RjDU0d0F\n"
"+3hQGNKShJyvvR6dM2Qzie8H2yA7QrLdRX8XywIDAQABAoIBABl0MmEw8HUd0DN0\n"
"R58lZUgUYtQp+MDJ5M3EEth7YYSt92WA91CG7y1lTbvEIJzdLs50ON0l/K7Njg0V\n"
"DaW6fVCQt1UX9PrvS3ckzgNR6emqKVmJqbIK14msiUPZ+C36xkJ8QTX6RG4E4HFP\n"
"EWHsqMJOeWQK/U4m/8Ix3rtihbo0/ihfkc31HeLMqOzomf3d4XNxg9idmEPYpFrC\n"
"XlusQTql6FCC8hKeayPcETVQ1x7iu2rg6zhKNmfosAUYuefCRA4KUvHbwkjwwpwh\n"
"em76wMDGY5T06orFn13bQ2b3qP9aptK9Bj8lY3BQEkqKAHcAPf+31l5UZbcUStTg\n"
"PrFD8AECgYEA7dNZav257Naqg2qGt157ILukRIdCj8BqCq7awzlJQ7dNAO9zPEBf\n"
"cKEJAN3hrlJsT72lWkbGoLUGUGLmL+jUR2VP80+ETEeCxU/EErue6SRyXHC7triY\n"
"4VGX8vmUtdeeOEyl+2QcIgwldQL0skyKl69GzKeH+mQbXtA+IXmEH8sCgYEAw4p3\n"
"+mKIPu6alZm3/LeEzUavApiUP+w/0dLnSpAhs7vjn+Jv2eQBm5ymg0dBkZuRNXmh\n"
"p4dik4PlILPITq+T9GyVMg4g0utX9Xz78uGlKrNzWj2yMLv0o0l4FnW8aykHIoRi\n"
"B2+zTxfB3gMckvJ++VWs4q8kZWCpM7onsSIh6AECgYEArHvrTyCDttSdyD/7QoSA\n"
"kmXkplrfGHj5r5PPT2V90GHhtDr1/Y3Gal4wtHM32YEn0tF9WjMYnbeMw8Jmpfqb\n"
"8sf0q0dRcS0wF8BZOSjgAMERPB/61HOfVVMi+/KtOxENTFGy09dwW/UpOWsSYzoG\n"
"DiruE0Gx6hSukR5A4XBLNe8CgYBjyrjsOXja1R5jFq4E9Qt7T4VlR8Tw0nrHdGDB\n"
"dskcVtkV8ZOvmWMQrWN1P9pAmyoCJm7PdpJiQj+e7uFc9tIFPZzujLNHsP+UsxJJ\n"
"o8qM/kPyW+YiZOm2o3n7zF46OhgAD5uPu/vAc5lm2iOtAsC2MnkmvsdOTYRMd8Zl\n"
"6ctwAQKBgQDe0tEm8EkIIwHm/yYpkGb3NXA/e+SM8o1Qcpl1N3A9yfU+dPxklLXE\n"
"rFfELDn3vi26KPhoE1d7hOr6Goy/63Mryp+4VKNEKspDnqWvECr/oMeANu0qNRtn\n"
"YVD6e1rWtZe007GVQfM+HJD9AFHSRwdAsrLNDDe8l7S984C/2ua5kg==\n"
"-----END RSA PRIVATE KEY-----";
21 changes: 21 additions & 0 deletions src/WiFi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ extern "C" {
#include "utility/debug.h"
}

void WPA2EnterpriseClass::addCACertificate(const char* ca_pem) {
WiFiDrv::wpa2EntSetCACertificate(ca_pem);
}

void WPA2EnterpriseClass::addClientCertificate(const char* client_crt, const char* client_key) {
// TODO: make sure that client_crt is not bigger tahn 4050bytes
WiFiDrv::wpa2EntSetClientCertificate(client_crt, client_key);
}

// singleton
WPA2EnterpriseClass WPA2Enterprise;

WiFiClass::WiFiClass() : _timeout(50000)
{
}
Expand Down Expand Up @@ -156,6 +168,15 @@ uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase, uint8_t cha
return status;
}

int WiFiClass::beginEnterprise(const char *ssid, const char* username, const char* password)
{
WiFiDrv::wpa2EntSetIdentity(username);
WiFiDrv::wpa2EntSetUsername(username);
WiFiDrv::wpa2EntSetPassword(password);
WiFiDrv::wpa2EntEnable();
return begin(ssid);
}

void WiFiClass::config(IPAddress local_ip)
{
WiFiDrv::config(1, (uint32_t)local_ip, 0, 0);
Expand Down
25 changes: 25 additions & 0 deletions src/WiFi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ extern "C" {
#include "WiFiSSLClient.h"
#include "WiFiServer.h"

typedef enum _eap_methods {
EAP_TLS = 0,
EAP_PEAP = 1,
EAP_TTLS = 2,
} eap_method;

class WPA2EnterpriseClass
{
public:
void clear();
void save();
void addCACertificate(const char* ca_pem);
void addClientCertificate(const char* client_crt, const char* client_key);
};

extern WPA2EnterpriseClass WPA2Enterprise;

class WiFiClass
{
private:
Expand Down Expand Up @@ -80,6 +97,14 @@ class WiFiClass
uint8_t beginAP(const char *ssid, const char* passphrase);
uint8_t beginAP(const char *ssid, const char* passphrase, uint8_t channel);

/* Start Wifi connection with wpa2 enterprise
*
* helper function for most university WPA2 connections
* if a fine-grained configuration is needed (like adding certificates)
* use WPA2Enterprise functions and then call begin() normally
*/
int beginEnterprise(const char *ssid, const char* username, const char* password);

/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
Expand Down
Loading