diff --git a/extras/test/src/test_provisioning_command_encode.cpp b/extras/test/src/test_provisioning_command_encode.cpp index 529df0c..2211ee7 100644 --- a/extras/test/src/test_provisioning_command_encode.cpp +++ b/extras/test/src/test_provisioning_command_encode.cpp @@ -181,6 +181,66 @@ } } + WHEN("Encode a message with provisioning public key") + { + ProvPublicKeyProvisioningMessage command; + command.c.id = ProvisioningMessageId::ProvPublicKeyProvisioningMessageId; + command.provPublicKey = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7JxCtXl5SvIrHmiasqyN4pyoXRlm44d5WXNpqmvJ\nk0tH8UpmIeHG7YPAkKLaqid95v/wLVoWeX5EbjxmlCkFtw==\n-----END PUBLIC KEY-----\n"; + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00012017 # tag(73751) + // 81 # array(1) + // 78 B4 # text(180) + // 2D 2D 2D 2D 2D 4245 47 49 4E 20 50 55 42 4C 49 43204B45592D2D2D2D2D0A0A4D466B77457759484B6F5A497A6A3043415159494B6F5A497A6A3044415163445167414537 + // 4A784374586C3553764972486D69617371794E3470796F58526C6D3434643557584E70716D764A0A6B3074483855706D49654847375950416B4B4C617169643935762F774C566F5765583545626A786D6C436B4674773D3D0A0A2D2D2D2D2D454E44205055424C4943204B45592D2D2D2D2D0A + + uint8_t expected_result[] = { + 0xDA, 0x00, 0x01, 0x20, 0x17, 0x81, 0x78, 0xB2, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, + 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, 0x77, + 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, + 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, + 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, + 0x37, 0x4A, 0x78, 0x43, 0x74, 0x58, 0x6C, 0x35, 0x53, 0x76, 0x49, 0x72, + 0x48, 0x6D, 0x69, 0x61, 0x73, 0x71, 0x79, 0x4E, 0x34, 0x70, 0x79, 0x6F, + 0x58, 0x52, 0x6C, 0x6D, 0x34, 0x34, 0x64, 0x35, 0x57, 0x58, 0x4E, 0x70, + 0x71, 0x6D, 0x76, 0x4A, 0x0A, 0x6B, 0x30, 0x74, 0x48, 0x38, 0x55, 0x70, + 0x6D, 0x49, 0x65, 0x48, 0x47, 0x37, 0x59, 0x50, 0x41, 0x6B, 0x4B, 0x4C, + 0x61, 0x71, 0x69, 0x64, 0x39, 0x35, 0x76, 0x2F, 0x77, 0x4C, 0x56, 0x6F, + 0x57, 0x65, 0x58, 0x35, 0x45, 0x62, 0x6A, 0x78, 0x6D, 0x6C, 0x43, 0x6B, + 0x46, 0x74, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, + 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, + 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A + }; + + THEN("The encoding is successful") { + REQUIRE(err == MessageEncoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + WHEN("Encode a message with provisioning public key") + { + ProvPublicKeyProvisioningMessage command; + command.c.id = ProvisioningMessageId::ProvPublicKeyProvisioningMessageId; + command.provPublicKey = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7JxCtXl5SvIrHmiasqyN4pyoXRlm44d5WXNpqmvJ\nk0tH8UpmIeHG7YPAkKLaqid95v/wLVoWeX5EbjxmlCkFtw==\n-----END PUBLIC KEY-----\n"; + uint8_t buffer[50]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is failing") { + REQUIRE(err == MessageEncoder::Status::Error); + } + } + WHEN("Encode a message with provisioning ble mac Address ") { BLEMacAddressProvisioningMessage command; @@ -256,7 +316,6 @@ // 81 # array(1) // 65 # text(5) // 312E362E30 # "1.6.0" - printf("res %d\n", (int)err); THEN("The encoding is successful") { REQUIRE(err == MessageEncoder::Status::Complete); REQUIRE(bytes_encoded == sizeof(expected_result)); diff --git a/src/Arduino_NetworkConfigurator.cpp b/src/Arduino_NetworkConfigurator.cpp index 40c33c4..e20a89c 100644 --- a/src/Arduino_NetworkConfigurator.cpp +++ b/src/Arduino_NetworkConfigurator.cpp @@ -49,19 +49,9 @@ bool NetworkConfiguratorClass::begin() { if(_state != NetworkConfiguratorStates::END) { return true; } - /* - * If the board is zero touch capable, starts with zero touch configuration mode - * In this state the board will try to connect to the network using a set of - * default network settings ex. Ethernet with DHCP - * This mode will fail if the provided ConnectionHandler is not GenericConnectionHandler type - * falling back to read the network settings from the storage - */ - #if ZERO_TOUCH_ENABLED - _state = NetworkConfiguratorStates::ZERO_TOUCH_CONFIG; - #else _state = NetworkConfiguratorStates::READ_STORED_CONFIG; - #endif + _connectionHandler->enableCheckInternetAvailability(true); memset(&_networkSetting, 0x00, sizeof(models::NetworkSetting)); @@ -98,10 +88,10 @@ NetworkConfiguratorStates NetworkConfiguratorClass::update() { _ledFeedback->update(); switch (_state) { + case NetworkConfiguratorStates::READ_STORED_CONFIG: nextState = handleReadStorage (); break; #if ZERO_TOUCH_ENABLED case NetworkConfiguratorStates::ZERO_TOUCH_CONFIG: nextState = handleZeroTouchConfig(); break; #endif - case NetworkConfiguratorStates::READ_STORED_CONFIG: nextState = handleReadStorage (); break; case NetworkConfiguratorStates::WAITING_FOR_CONFIG: nextState = handleWaitingForConf (); break; case NetworkConfiguratorStates::CONNECTING: nextState = handleConnecting (); break; case NetworkConfiguratorStates::CONFIGURED: nextState = handleConfigured (); break; @@ -475,9 +465,10 @@ NetworkConfiguratorStates NetworkConfiguratorClass::handleZeroTouchConfig() { sendStatus(StatusMessage::ERROR); } _connectionHandlerIstantiated = false; - return NetworkConfiguratorStates::READ_STORED_CONFIG; + return NetworkConfiguratorStates::WAITING_FOR_CONFIG; } - return NetworkConfiguratorStates::ZERO_TOUCH_CONFIG; + + return handleWaitingForConf(); } #endif @@ -512,13 +503,26 @@ NetworkConfiguratorStates NetworkConfiguratorClass::handleReadStorage() { if(credFound && _connectionHandler->updateSetting(_networkSetting)) { _connectionHandlerIstantiated = true; + _configInProgress = _agentsManager->isConfigInProgress(); + if (_configInProgress) { + return NetworkConfiguratorStates::UPDATING_CONFIG; + } return NetworkConfiguratorStates::CONFIGURED; } if (_optionUpdateTimer.getWaitTime() == 0) { scanNetworkOptions(); } + /* + * If the board is zero touch capable and without network configuration, it starts the zero touch configuration mode + * In this state the board will try to connect to the network using a set of + * default network settings ex. Ethernet with DHCP + */ + #if ZERO_TOUCH_ENABLED + return NetworkConfiguratorStates::ZERO_TOUCH_CONFIG; + #else return NetworkConfiguratorStates::WAITING_FOR_CONFIG; + #endif } NetworkConfiguratorStates NetworkConfiguratorClass::handleWaitingForConf() { @@ -583,7 +587,8 @@ NetworkConfiguratorStates NetworkConfiguratorClass::handleConfigured() { } NetworkConfiguratorStates NetworkConfiguratorClass::handleUpdatingConfig() { - if (_agentsManager->isConfigInProgress() == false) { + _configInProgress = _agentsManager->isConfigInProgress(); + if (_configInProgress == false) { //If peer disconnects without updating the network settings, go to connecting state for check the connection sendStatus(StatusMessage::CONNECTING); return NetworkConfiguratorStates::CONNECTING; diff --git a/src/configuratorAgents/AgentsManager.cpp b/src/configuratorAgents/AgentsManager.cpp index bff98ee..edc3d14 100644 --- a/src/configuratorAgents/AgentsManager.cpp +++ b/src/configuratorAgents/AgentsManager.cpp @@ -316,6 +316,7 @@ void AgentsManagerClass::updateProgressRequest(MessageOutputType type) { case MessageOutputType::WIFI_FW_VERSION: key = RequestType::GET_WIFI_FW_VERSION ; break; case MessageOutputType::PROV_SKETCH_VERSION: key = RequestType::GET_PROVISIONING_SKETCH_VERSION; break; case MessageOutputType::NETCONFIG_LIB_VERSION: key = RequestType::GET_NETCONFIG_LIB_VERSION ; break; + case MessageOutputType::PROV_PUBLIC_KEY: key = RequestType::GET_ID ; break; } if (key == RequestType::NONE) { @@ -324,7 +325,7 @@ void AgentsManagerClass::updateProgressRequest(MessageOutputType type) { if( key == RequestType::GET_ID && _statusRequest.key == key && _statusRequest.pending){ _statusRequest.completion++; - if(_statusRequest.completion == 2){ + if(_statusRequest.completion == 3){ _statusRequest.reset(); } return; diff --git a/src/configuratorAgents/MessagesDefinitions.h b/src/configuratorAgents/MessagesDefinitions.h index 2f2d460..de456c8 100644 --- a/src/configuratorAgents/MessagesDefinitions.h +++ b/src/configuratorAgents/MessagesDefinitions.h @@ -61,6 +61,7 @@ enum class MessageOutputType { STATUS, WIFI_FW_VERSION, PROV_SKETCH_VERSION, NETCONFIG_LIB_VERSION, + PROV_PUBLIC_KEY }; /* Types of ingoing messages */ @@ -86,6 +87,7 @@ struct ProvisioningOutputMessage { const char *wifiFwVersion; const char *provSketchVersion; const char *netConfigLibVersion; + const char *provPublicKey; } m; }; diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.cpp b/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.cpp index e0d856f..764c5ce 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.cpp +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.cpp @@ -75,6 +75,9 @@ bool BoardConfigurationProtocol::sendMsg(ProvisioningOutputMessage &msg) { case MessageOutputType::NETCONFIG_LIB_VERSION: res = sendVersion(msg.m.netConfigLibVersion, msg.type); break; + case MessageOutputType::PROV_PUBLIC_KEY: + res = sendProvPublicKey(msg.m.provPublicKey, strlen(msg.m.provPublicKey)); + break; default: break; } @@ -294,6 +297,23 @@ bool BoardConfigurationProtocol::sendJwt(const char *jwt, size_t len) { return res; } +bool BoardConfigurationProtocol::sendProvPublicKey(const char *provPublicKey, size_t len) { + + size_t cborDataLen = CBOR_MIN_PROV_PUBIC_KEY_LEN + len; + uint8_t data[cborDataLen]; + + if (!CBORAdapter::provPublicKeyToCBOR(provPublicKey, data, &cborDataLen)) { + return false; + } + + if (!sendData(PacketManager::MessageType::DATA, data, cborDataLen)) { + DEBUG_WARNING("BoardConfigurationProtocol::%s failed to send JWT", __FUNCTION__); + return false; + } + + return true; +} + bool BoardConfigurationProtocol::sendBleMacAddress(const uint8_t *mac, size_t len) { bool res = false; if (len != BLE_MAC_ADDRESS_SIZE) { diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.h b/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.h index 3a82291..e206f62 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.h +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/BoardConfigurationProtocol.h @@ -96,6 +96,7 @@ class BoardConfigurationProtocol { bool sendNetworkOptions(const NetworkOptions *netOptions); bool sendUhwid(const byte *uhwid); bool sendJwt(const char *jwt, size_t len); + bool sendProvPublicKey(const char *provPublicKey, size_t len); bool sendBleMacAddress(const uint8_t *mac, size_t len); bool sendVersion(const char *version, MessageOutputType type); TransmissionResult transmitStream(); diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.cpp b/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.cpp index 5442932..0f7a5a4 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.cpp +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.cpp @@ -68,6 +68,20 @@ bool CBORAdapter::BLEMacAddressToCBOR(const uint8_t *mac, uint8_t *data, size_t return status == MessageEncoder::Status::Complete ? true : false; } +bool CBORAdapter::provPublicKeyToCBOR(const char *provPublicKey, uint8_t *data, size_t *len) { + CBORMessageEncoder encoder; + if(*len < CBOR_MIN_PROV_PUBIC_KEY_LEN + strlen(provPublicKey)) { + return false; + } + ProvPublicKeyProvisioningMessage provPublicKeyMsg; + provPublicKeyMsg.c.id = ProvisioningMessageId::ProvPublicKeyProvisioningMessageId; + provPublicKeyMsg.provPublicKey = provPublicKey; + + MessageEncoder::Status status = encoder.encode((Message *)&provPublicKeyMsg, data, *len); + + return status == MessageEncoder::Status::Complete ? true : false; +} + bool CBORAdapter::statusToCBOR(StatusMessage msg, uint8_t *data, size_t *len) { bool result = false; diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.h b/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.h index 09aeef8..5ec177b 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.h +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/CBORAdapter.h @@ -21,11 +21,13 @@ #define CBOR_MIN_WIFI_FW_VERSION_LEN CBOR_DATA_HEADER_LEN + 1 // CBOR_DATA_HEADER_LEN + 1 byte for the length of the string #define CBOR_MIN_PROV_SKETCH_VERSION_LEN CBOR_DATA_HEADER_LEN + 1 // CBOR_DATA_HEADER_LEN + 1 byte for the length of the string #define CBOR_MIN_NETCONFIG_LIB_VERSION_LEN CBOR_DATA_HEADER_LEN + 1 // CBOR_DATA_HEADER_LEN + 1 byte for the length of the string +#define CBOR_MIN_PROV_PUBIC_KEY_LEN CBOR_DATA_HEADER_LEN + 3 // CBOR_DATA_HEADER_LEN + 2 bytes for the length of the string + 1 byte for the type of the string class CBORAdapter { public: static bool uhwidToCBOR(const byte *uhwid, uint8_t *data, size_t *len); static bool jwtToCBOR(const char *jwt, uint8_t *data, size_t *len); + static bool provPublicKeyToCBOR(const char *provPublicKey, uint8_t *data, size_t *len); static bool BLEMacAddressToCBOR(const uint8_t *mac, uint8_t *data, size_t *len); static bool wifiFWVersionToCBOR(const char *wifiFWVersion, uint8_t *data, size_t *len); static bool provSketchVersionToCBOR(const char *provSketchVersion, uint8_t *data, size_t *len); diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/CBORInstances.h b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/CBORInstances.h index dbca315..2442db1 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/CBORInstances.h +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/CBORInstances.h @@ -7,6 +7,7 @@ static StatusProvisioningMessageEncoder statusProvisioningMessageEnc static ListWifiNetworksProvisioningMessageEncoder listWifiNetworksProvisioningMessageEncoder; static UniqueHardwareIdProvisioningMessageEncoder uniqueHardwareIdProvisioningMessageEncoder; static JWTProvisioningMessageEncoder jWTProvisioningMessageEncoder; +static ProvPublicKeyProvisioningMessageEncoder provPublicKeyProvisioningMessageEncoder; static BLEMacAddressProvisioningMessageEncoder bLEMacAddressProvisioningMessageEncoder; static ProvSketchVersionProvisioningMessageEncoder provSketchVersionProvisioningMessageEncoder; static NetConfigLibVersProvisioningMessageEncoder netConfigLibVersProvisioningMessageEncoder; diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.cpp b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.cpp index 6c501f9..c688de2 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.cpp +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.cpp @@ -154,4 +154,23 @@ MessageEncoder::Status NetConfigLibVersProvisioningMessageEncoder::encode(CborEn return MessageEncoder::Status::Complete; } +MessageEncoder::Status ProvPublicKeyProvisioningMessageEncoder::encode(CborEncoder *encoder, Message *msg) { + ProvPublicKeyProvisioningMessage * provisioningProvPublicKey = (ProvPublicKeyProvisioningMessage*) msg; + CborEncoder array_encoder; + + if(cbor_encoder_create_array(encoder, &array_encoder, 1) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_text_stringz(&array_encoder, provisioningProvPublicKey->provPublicKey) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + #endif // NETWORK_CONFIGURATOR_COMPATIBLE diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.h b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.h index 25934f4..03ca489 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.h +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/Encoder.h @@ -67,3 +67,11 @@ class NetConfigLibVersProvisioningMessageEncoder: public CBORMessageEncoderInter protected: MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; }; + +class ProvPublicKeyProvisioningMessageEncoder: public CBORMessageEncoderInterface { + public: + ProvPublicKeyProvisioningMessageEncoder() + : CBORMessageEncoderInterface(CBORProvPublicKeyProvisioningMessage, ProvPublicKeyProvisioningMessageId) {} + protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; + }; diff --git a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/ProvisioningMessage.h b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/ProvisioningMessage.h index d48800d..51d2395 100644 --- a/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/ProvisioningMessage.h +++ b/src/configuratorAgents/agents/boardConfigurationProtocol/cbor/ProvisioningMessage.h @@ -50,6 +50,7 @@ enum CBORProvisioningMessageTag: CBORTag { CBORBLEMacAddressProvisioningMessage = 0x012013, CBORProvSketchVersionProvisioningMessage = 0x012015, CBORNetConfigLibVersProvisioningMessage = 0x012016, + CBORProvPublicKeyProvisioningMessage = 0x012017, }; enum ProvisioningMessageId: MessageId { @@ -61,6 +62,7 @@ enum ProvisioningMessageId: MessageId { ProvSketchVersionProvisioningMessageId, NetConfigLibVersProvisioningMessageId, JWTProvisioningMessageId, + ProvPublicKeyProvisioningMessageId, TimestampProvisioningMessageId, CommandsProvisioningMessageId, WifiConfigProvisioningMessageId, @@ -108,6 +110,13 @@ struct JWTProvisioningMessage { }; }; +struct ProvPublicKeyProvisioningMessage { + ProvisioningMessage c; + struct { + const char *provPublicKey; //The payload is a string. + }; +}; + struct BLEMacAddressProvisioningMessage { ProvisioningMessage c; struct {