Closed tpbedford-oomdata closed 4 weeks ago
I've enabled further WPA supplicant logging, and it appears my cert is encrypted using an algorithm/digest that is not supported by mbedtls. Thus, possibly the ESP-IDF is failling to use a client cert so it reverts to PEAP (where I believe it is optional) even if a username/password isn't configured.
Method esp_eap_client_set_certificate_and_key() returns no error - it only fails to decrypt the password during the connection attempt in the background and seems to only print an error if "Print debug messages from WPA Supplicant" is turned on in idf.py menuconfig
Hi @tpbedford-oomdata, is it possible to share more details about the cert encryption? yes, wpa_supplicant logs are disabled by default.
@kapilkedawat The encryption used for the private key was des-ede3-cbc which I can see is not compiled in (MBEDTLS_DES_C is not defined by default). Once I decrypted the cert it worked OK, so I'll recrypt it with a supported algorithm for my case.
So ultimately I suppose esp_eap_client_set_certificate_and_key() should not return ESP_OK when given an unsupported cert. My cert was encrypted with des-ede3-cbc which was not supported, but this method accepted my cert. Only after esp_wifi_connect() was called, that somewhere in the background this decryption failed, and there was no error message to indicate why. The WIFI_EVENT_STA_DISCONNECTED event gave reason as WIFI_REASON_802_1X_AUTH_FAILED which doesn't tell the user anything useful.
@kapilkedawat Further, the esp_eap_client_set_certificate_and_key() method appears to require len+1 to work. I'm reading my cert file from FAT filesystem and gave the actual length of the file. Only once I added an additional NUL and used len+1 did it succeed.
e.g.
FILE* f = fopen("mycert.pem"); // is 3048 bytes
size_t cert_len = fread(cert_buf, ..., f); // len = 3048
esp_eap_client_set_certificate_and_key(cert_buf, cert_len, pkey_buf, pkey_len, NULL, 0); // FAILS if cert_len=3048
cert_buf[cert_len] = 0; // add NUL
esp_eap_client_set_certificate_and_key(cert_buf, cert_len+1, pkey_buf, pkey_len+1, NULL, 0); // succeeds passing 3049 instead
Hi @tpbedford-oomdata,
Yes esp_eap_client_set_certificate_and_key()
API needs zero terminated strings. Please see https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/network/esp_wifi.html?highlight=esp_eap_client_set_certificate_and_key#_CPPv438esp_eap_client_set_certificate_and_keyPKhiPKhiPKhi .
The API returns ESP_OK because we do not attempt to parse the certificates until initiating the EAP connection. Performing this operation before establishing the connection would cause unnecessary overhead.
The API returns ESP_OK because we do not attempt to parse the certificates until initiating the EAP connection. Performing this operation before establishing the connection would cause unnecessary overhead.
Noted ("The client_cert, private_key, and private_key_password should be zero-terminated.") but, a) it's not clear from the doc that len argument must be strlen(cert)+1 and not strlen(cert) b) why require len as an argument at all if the cert strings are null-terminated?
I personally think the overhead of parsing the cert when calling esp_eap_client_set_certificate_and_key() would be OK: it's an infrequent operation, done once when initialising wifi, which takes several seconds to connect anyway, and otherwise there is no indication to the caller why the wifi connection attempt failed. The WIFI_EVENT event doesn't carry enough information to know if it's a bad cert, bad password, bad key, unsupported encryption algo, etc.
The API returns ESP_OK because we do not attempt to parse the certificates until initiating the EAP connection. Performing this operation before establishing the connection would cause unnecessary overhead.
Noted ("The client_cert, private_key, and private_key_password should be zero-terminated.") but, a) it's not clear from the doc that len argument must be strlen(cert)+1 and not strlen(cert) b) why require len as an argument at all if the cert strings are null-terminated?
len is required since there may be chain of certs.
I personally think the overhead of parsing the cert when calling esp_eap_client_set_certificate_and_key() would be OK: it's an infrequent operation, done once when initialising wifi, which takes several seconds to connect anyway, and otherwise there is no indication to the caller why the wifi connection attempt failed. The WIFI_EVENT event doesn't carry enough information to know if it's a bad cert, bad password, bad key, unsupported encryption algo, etc.
thanks for your input, we will take it into consideration.
Thanks for reporting, we will close this issue. Feel free to reopen if have more updates. Thanks for using our Espressif product!
Answers checklist.
General issue report
I am attempting to connect to WPA2 Enterprise wifi which requires EAP-TLS. I call the ESP's enterprise wifi API similarly to the example/wifi-enterprise code when configured for EAP-TLS (i.e. not PEAP or TTLS). Yet, the Enterprise AP reports that the ESP is proposing PEAP, which it doesn't support and the authentication is rejected.
I'm using ESP-IDF 5.1 (as I'm also using ESP-ADF v2.6 and that's the latest supported ESP-IDF version)
My code:
For comparison, the example/wifi-enterprise code uses esp_wifi_set_config() before the enterprise API, but otherwise the same calls:
The Cisco enterprise AP event logs (where XXXXXX correctly displays my EAP identity)
And finally quote from my network engineer with logs from their Cisco Enterprise AP: