1
0
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:
Ivan Grokhotkov 2015-09-14 10:22:54 +03:00
parent c970dec6a7
commit f73d414f38
5 changed files with 65 additions and 2 deletions

View File

@ -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);

View File

@ -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()) {

View File

@ -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;

View File

@ -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.