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 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() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
@ -35,9 +39,7 @@ void setup() {
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
|
||||
// Use WiFiClientSecure class to create TLS connection
|
||||
|
||||
WiFiClientSecure client;
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(host);
|
||||
@ -46,6 +48,12 @@ void setup() {
|
||||
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";
|
||||
Serial.print("requesting URL: ");
|
||||
Serial.println(url);
|
||||
|
@ -242,6 +242,50 @@ void WiFiClientSecure::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) {
|
||||
ClientContext* _client = reinterpret_cast<ClientContext*>(fd);
|
||||
if (_client->state() != ESTABLISHED && !_client->getSize()) {
|
||||
|
@ -38,6 +38,8 @@ public:
|
||||
int connect(IPAddress ip, 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;
|
||||
int read(uint8_t *buf, size_t size) 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);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user