From 87ce4d473da9d3b6f7805f62a6fd538139277007 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 18:03:29 +0200 Subject: [PATCH] Initial TLS connection --- base-firmware/files/config.json | 10 +++- master/README.md | 3 ++ spejsiot/Endpoint.cpp | 4 +- spejsiot/SpejsNode.cpp | 87 +++++++++++++++++++++++---------- spejsiot/SpejsNode.h | 2 +- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/base-firmware/files/config.json b/base-firmware/files/config.json index df09c94..407d6f0 100644 --- a/base-firmware/files/config.json +++ b/base-firmware/files/config.json @@ -1,5 +1,5 @@ { - "name": "testdev", + "name": "unprovisioned", "extras": { "owner": "informatic", @@ -10,5 +10,11 @@ "out": {"type": "output", "gpio": 2}, "testInput": {"type": "input", "gpio": 3}, "testtemp": {"type": "dht"} - } + }, + + "broker": "mqtts://10.8.0.136:8883", + "brokerSHA1": "E7:FA:91:2B:E9:D6:7E:55:83:16:8D:09:68:BF:DD:4F:5D:F4:AC:DA", + "brokerSHA256": "29:10:5e:29:27:d6:2f:05:21:cc:8b:0e:f2:ca:e9:aa:1d:f4:1a:63:58:ed:4e:c8:92:b2:cb:9e:d7:71:a9:1d", + "brokerClient": "testing", + "brokerUseTLS": true } diff --git a/master/README.md b/master/README.md index f5b19a5..41e9911 100644 --- a/master/README.md +++ b/master/README.md @@ -6,4 +6,7 @@ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out s # Extract SHA-1 openssl x509 -in server.crt -sha1 -noout -fingerprint | sed 's/.*=/0x/g; s/:/, 0x/g' + +# extract sha256 +openssl x509 -in mqtt/certs/server.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 | sed -r 's/.*= //g; s/([0-9a-z]{2})/\1:/g; s/:$//g' ``` diff --git a/spejsiot/Endpoint.cpp b/spejsiot/Endpoint.cpp index 2212992..cfe66c5 100644 --- a/spejsiot/Endpoint.cpp +++ b/spejsiot/Endpoint.cpp @@ -13,7 +13,9 @@ void Endpoint::notify(String property, String value) { void Endpoint::onConnected() { parent->subscribe(name + "/+/set"); - parent->notify(name + "/$type", type); + if (type.length()) { + parent->notify(name + "/$type", type); + } } void Endpoint::onMessage(String topic, String payload) { diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index 579d436..b8a585a 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -59,10 +59,19 @@ void SpejsNode::loadJSON(std::vector initializers) { if (fileExist(CONFIG_FILE)) { int size = fileGetSize(CONFIG_FILE); debugf("Found config file, %d bytes", size); + char* jsonString = new char[size + 1]; + if (jsonString == nullptr) { + debugf("CAN'T CALLOCATE JSONSTRING"); + return; + } + debugf("allocated %08x",jsonString); + fileGetContent(CONFIG_FILE, jsonString, size + 1); + debugf("loaded %s", jsonString); JsonObject& root = jsonBuffer.parseObject(jsonString); + debugf("parsed: %d", root.success()); if (!root.success()) { debugf("invalid config"); return; @@ -71,6 +80,8 @@ void SpejsNode::loadJSON(std::vector initializers) { if (root.containsKey("name")) deviceType = (root["name"]).asString(); + debugf("Loading networks..."); + JsonArray& networks = root.get("networks"); if (networks.success() && networks.size()) { debugf("got networks"); @@ -86,13 +97,15 @@ void SpejsNode::loadJSON(std::vector initializers) { } // Broker configuration + debugf("Loading broker configuration..."); if (root.containsKey("broker")) { auto brokerPort = root.containsKey("brokerPort") ? root["brokerPort"] : 1883; brokerUseTLS = root["brokerUseTLS"]; brokerURL = root["broker"].as(); - String hash = root.get("brokerSHA1"); + String hash = root.get("brokerSHA256"); if ((hash.length() + 1) % 3 == 0) { + debugf("Loading sha256 certificate/pubkey hash"); int hashLength = (hash.length() + 1) / 3; uint8_t* hashBlob = new uint8_t[hashLength]; @@ -100,11 +113,17 @@ void SpejsNode::loadJSON(std::vector initializers) { hashBlob[i] = hexToInt(hash[3*i]) << 4 | hexToInt(hash[3*i+1]); } - fingerprints.certSha1 = hashBlob; + mqtt.pinCertificate(hashBlob, eSFT_PkSha256); } } + debugf("Loading endpoints..."); + JsonObject& data = root.get("endpoints"); + if (!data.success()) { + debugf("No endpoints found..."); + return; + } for (auto it: data) { bool found = false; @@ -155,7 +174,7 @@ void SpejsNode::keepAliveHandler() { } } -inline String SpejsNode::DEV_TOPIC(String t) { +String SpejsNode::DEV_TOPIC(String t) { return TOPIC_PREFIX + deviceID + "/" + t; } @@ -179,6 +198,16 @@ void SpejsNode::onConnected() { debugf("Connection successful"); + debugf("http init"); + + // HTTP initialization + http.listen(80); + http.paths.set("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); + http.paths.set("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); + http.paths.setDefault(HttpPathDelegate(&SpejsNode::httpFile, this)); + http.setBodyParser("application/json", bodyToStringParser); + + debugf("mqtt init"); mqtt.setMessageHandler([=](MqttClient& client, mqtt_message_t* message) -> int { if (message == nullptr) return -1; @@ -197,35 +226,38 @@ void SpejsNode::onConnected() { #ifdef ENABLE_SSL if (brokerUseTLS) { + debugf("Using TLS"); mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER); - mqtt.pinCertificate(fingerprints); + //mqtt.pinCertificate(fingerprints); } #endif + debugf("Connecting: %s as %s", brokerURL.c_str(), brokerClient.c_str()); + + mqtt.setConnectedHandler([=](MqttClient& client, mqtt_message_t* message) { + debugf("Initializing endpoints"); + for(unsigned int i = 0 ; i < endpoints.count() ; i++) { + endpoints.valueAt(i)->onConnected(); + } + + debugf("subscribing"); + subscribe("$implementation/+"); + + debugf("say hello"); + + // Say hello + notify("$online", "true"); + notify("$homie", "2"); + notify("$name", deviceType); + notify("$localip", WifiStation.getIP().toString()); + notify("$mac", WifiStation.getMAC()); + notify("$fw/name", "spejsiot"); + notify("$fw/version", BUILD_ID); + notify("$fw/slot", String(currentSlot)); + + return 0; + }); mqtt.connect(brokerURL, brokerClient); - - for(unsigned int i = 0 ; i < endpoints.count() ; i++) { - endpoints.valueAt(i)->onConnected(); - } - - subscribe("$implementation/+"); - - // Say hello - notify("$online", "true"); - notify("$homie", "2"); - notify("$name", deviceType); - notify("$localip", WifiStation.getIP().toString()); - notify("$mac", WifiStation.getMAC()); - notify("$fw/name", "spejsiot"); - notify("$fw/version", BUILD_ID); - notify("$implementation/slot", String(currentSlot)); - - // HTTP initialization - http.listen(80); - http.paths.set("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); - http.paths.set("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); - http.paths.setDefault(HttpPathDelegate(&SpejsNode::httpFile, this)); - http.setBodyParser("application/json", bodyToStringParser); } void SpejsNode::httpConfig(HttpRequest &request, HttpResponse &response) @@ -269,6 +301,7 @@ void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response) * Publish on device-specific topic */ bool SpejsNode::notify(String key, String value) { + debugf("%s [%d] = %s [%d]", key.c_str(), key.length(), value.c_str(), value.length()); mqtt.publish(DEV_TOPIC(key), value, true); return mqtt.getConnectionState() == eTCS_Connected; } diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h index cc61ca8..849c48f 100644 --- a/spejsiot/SpejsNode.h +++ b/spejsiot/SpejsNode.h @@ -77,7 +77,7 @@ protected: String wifiPassword = WIFI_PWD; String brokerURL = "mqtt://" MQTT_BROKER; - String brokerClient; + String brokerClient = ""; bool brokerUseTLS = false;