mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
WiFiClientSecure: add certificate fingerprint verification (#43)
This commit is contained in:
parent
c970dec6a7
commit
f73d414f38
@ -20,6 +20,10 @@ const char* password = "........";
|
|||||||
const char* host = "api.github.com";
|
const char* host = "api.github.com";
|
||||||
const int httpsPort = 443;
|
const int httpsPort = 443;
|
||||||
|
|
||||||
|
// Use web browser to view and copy
|
||||||
|
// SHA1 fingerprint of the certificate
|
||||||
|
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
@ -35,9 +39,7 @@ void setup() {
|
|||||||
Serial.println("IP address: ");
|
Serial.println("IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
|
||||||
// Use WiFiClientSecure class to create TLS connection
|
// Use WiFiClientSecure class to create TLS connection
|
||||||
|
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
Serial.print("connecting to ");
|
Serial.print("connecting to ");
|
||||||
Serial.println(host);
|
Serial.println(host);
|
||||||
@ -46,6 +48,12 @@ void setup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client.verify(fingerprint, host)) {
|
||||||
|
Serial.println("certificate matches");
|
||||||
|
} else {
|
||||||
|
Serial.println("certificate doesn't match");
|
||||||
|
}
|
||||||
|
|
||||||
String url = "/repos/esp8266/Arduino/commits/esp8266/status";
|
String url = "/repos/esp8266/Arduino/commits/esp8266/status";
|
||||||
Serial.print("requesting URL: ");
|
Serial.print("requesting URL: ");
|
||||||
Serial.println(url);
|
Serial.println(url);
|
||||||
|
@ -242,6 +242,50 @@ void WiFiClientSecure::stop() {
|
|||||||
return WiFiClient::stop();
|
return WiFiClient::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parseHexNibble(char pb, uint8_t* res) {
|
||||||
|
if (pb >= '0' && pb <= '9') {
|
||||||
|
*res = (uint8_t) (pb - '0'); return true;
|
||||||
|
}
|
||||||
|
else if (pb >= 'a' && pb <= 'f') {
|
||||||
|
*res = (uint8_t) (pb - 'a' + 10); return true;
|
||||||
|
}
|
||||||
|
else if (pb >= 'A' && pb <= 'F') {
|
||||||
|
*res = (uint8_t) (pb - 'A' + 10); return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiFiClientSecure::verify(const char* fp, const char* url) {
|
||||||
|
uint8_t sha1[20];
|
||||||
|
int len = strlen(fp);
|
||||||
|
int pos = 0;
|
||||||
|
for (int i = 0; i < sizeof(sha1); ++i) {
|
||||||
|
while (pos < len && fp[pos] == ' ') {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
DEBUGV("pos:%d ", pos);
|
||||||
|
if (pos > len - 2) {
|
||||||
|
DEBUGV("fingerprint too short\r\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t high, low;
|
||||||
|
if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) {
|
||||||
|
DEBUGV("invalid hex sequence: %c%c\r\n", fp[pos], fp[pos+1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pos += 2;
|
||||||
|
sha1[i] = low | (high << 4);
|
||||||
|
}
|
||||||
|
if (ssl_match_fingerprint(*_ssl, sha1) != 0) {
|
||||||
|
DEBUGV("fingerprint doesn't match\r\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: check URL against certificate
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" int ax_port_read(int fd, uint8_t* buffer, size_t count) {
|
extern "C" int ax_port_read(int fd, uint8_t* buffer, size_t count) {
|
||||||
ClientContext* _client = reinterpret_cast<ClientContext*>(fd);
|
ClientContext* _client = reinterpret_cast<ClientContext*>(fd);
|
||||||
if (_client->state() != ESTABLISHED && !_client->getSize()) {
|
if (_client->state() != ESTABLISHED && !_client->getSize()) {
|
||||||
|
@ -38,6 +38,8 @@ public:
|
|||||||
int connect(IPAddress ip, uint16_t port) override;
|
int connect(IPAddress ip, uint16_t port) override;
|
||||||
int connect(const char* name, uint16_t port) override;
|
int connect(const char* name, uint16_t port) override;
|
||||||
|
|
||||||
|
bool verify(const char* fingerprint, const char* url);
|
||||||
|
|
||||||
size_t write(const uint8_t *buf, size_t size) override;
|
size_t write(const uint8_t *buf, size_t size) override;
|
||||||
int read(uint8_t *buf, size_t size) override;
|
int read(uint8_t *buf, size_t size) override;
|
||||||
int available() override;
|
int available() override;
|
||||||
|
@ -375,6 +375,15 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code);
|
|||||||
*/
|
*/
|
||||||
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
|
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if certificate fingerprint (SHA1) matches the one given.
|
||||||
|
*
|
||||||
|
* @param ssl [in] An SSL object reference.
|
||||||
|
* @param fp [in] SHA1 fingerprint to match against
|
||||||
|
* @return SSL_OK if the certificate is verified.
|
||||||
|
*/
|
||||||
|
EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve an X.509 distinguished name component.
|
* @brief Retrieve an X.509 distinguished name component.
|
||||||
*
|
*
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user