MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification
Dependencies: MaximInterface mbed
The MAXREFDES143# is an Internet of Things (IoT) embedded security reference design, built to protect an industrial sensing node by means of authentication and notification to a web server. The hardware includes a peripheral module representing a protected sensor node monitoring operating temperature and remaining life of a filter (simulated through ambient light sensing) and an mbed shield representing a controller node responsible for monitoring one or more sensor nodes. The design is hierarchical with each controller node communicating data from connected sensor nodes to a web server that maintains a centralized log and dispatches notifications as necessary. The mbed shield contains a Wi-Fi module, a DS2465 coprocessor with 1-Wire® master function, an LCD, LEDs, and pushbuttons. The protected sensor node contains a DS28E15 authenticator, a DS7505 temperature sensor, and a MAX44009 light sensor. The mbed shield communicates to a web server by the onboard Wi-Fi module and to the protected sensor node with I2C and 1-Wire. The MAXREFDES143# is equipped with a standard shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The simplicity of this design enables rapid integration into any star-topology IoT network requiring the heightened security with low overhead provided by the SHA-256 symmetric-key algorithm.
More information about the MAXREFDES143# is available on the Maxim Integrated website.
Diff: Factory.cpp
- Revision:
- 32:0a09505a656d
- Parent:
- 25:37ea43ff81be
diff -r 7b10bcb3e0fc -r 0a09505a656d Factory.cpp
--- a/Factory.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/Factory.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,127 +28,160 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
+#include <MaximInterface/Devices/DS2465.hpp>
+#include <MaximInterface/Devices/DS28E15_22_25.hpp>
+#include <MaximInterface/Utilities/Segment.hpp>
#include "Factory.hpp"
#include "SensorNode.hpp"
-#include "Masters/DS2465/DS2465.h"
-#include "Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.h"
-#include "wait_api.h"
-using namespace OneWire;
+using namespace MaximInterface;
/// The valid master secret for the system.
-static const DS2465::Secret masterSecret = { { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x21,
- 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x32 } };
+static const Sha256::Hash masterSecret = {
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x32};
/// An invalid master secret for example purposes.
-static const DS2465::Secret invalidMasterSecret = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
+static const Sha256::Hash invalidMasterSecret = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-bool provisionCoprocessor(DS2465 & ds2465)
-{
- bool result = (ds2465.setMasterSecret(masterSecret) == ISha256MacCoproc::Success);
- if (result)
- {
+bool provisionCoprocessor(DS2465 & ds2465) {
+ bool result = !ds2465.writeMasterSecret(masterSecret);
+ if (result) {
SensorNode::AuthData authData;
- DS28E15_22_25::Page pageData;
+ DS28E15::Page pageData;
pageData.fill(uint8_t(SensorNode::defaultPaddingByte));
- std::copy(authData.segment.begin(), authData.segment.end(), pageData.begin());
- result = (ds2465.writeScratchpad(pageData.data(), pageData.size()) == OneWireMaster::Success);
+ const std::pair<DS28E15::Page::iterator, DS28E15::Page::iterator>
+ pageSegment =
+ createSegment(pageData.begin(), pageData.end(),
+ authData.segment.size(), authData.segmentNum);
+ if (pageSegment.first != pageData.end()) {
+ std::copy(authData.segment.begin(), authData.segment.end(),
+ pageSegment.first);
+ }
+ result = !ds2465.writePage(0, pageData);
}
- if (result)
- {
- result = (ds2465.copyScratchpadToPage(0) == OneWireMaster::Success);
- if (result)
- wait_ms(DS2465::eepromPageWriteDelayMs);
- }
-
return result;
}
-bool provisionSensorNode(SensorNode & sensorNode, bool validSecret)
-{
+bool provisionSensorNode(SensorNode & sensorNode, bool validSecret) {
const int blockNum = sensorNode.authData.pageNum / 2;
- const DS28E15_22_25::BlockProtection desiredProtection(false, false, false, true, blockNum); // Authentication Protection only
-
+ const DS28E15::BlockProtection desiredProtection(
+ false, false, false, true, blockNum); // Authentication Protection only
+
// Reset to starting defaults
sensorNode.authData.reset();
-
+
// Read current protection status
- DS28E15_22_25::BlockProtection protectionStatus;
- bool result;
- // Read block protections
- result = (sensorNode.ds28e15.readBlockProtection(blockNum, protectionStatus) == OneWireSlave::Success);
+ DS28E15::BlockProtection protectionStatus;
+ bool result =
+ !sensorNode.ds28e15.readBlockProtection(blockNum, protectionStatus);
// Check if invalid protections are set
if (result)
- result = ((protectionStatus.statusByte() & ~(desiredProtection.statusByte())) == 0x00);
+ result = ((protectionStatus.statusByte() &
+ ~(desiredProtection.statusByte())) == 0x00);
// Load secret into scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(validSecret ? masterSecret : invalidMasterSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(
+ validSecret ? masterSecret : invalidMasterSecret);
// Load master secret from scratchpad without locking
if (result)
- result = (sensorNode.ds28e15.loadSecret(false) == OneWireSlave::Success);
-
+ result = !sensorNode.ds28e15.loadSecret(false);
+
// Setup is complete if not using a valid secret
if (!validSecret)
return result;
-
+
// Create constant partial secret
- DS28E15_22_25::Scratchpad partialSecret;
- DS28E15_22_25::Page pageData;
+ DS28E15::Scratchpad partialSecret;
+ DS28E15::Page pageData;
partialSecret.fill(uint8_t(SensorNode::defaultPaddingByte));
-
+
// Read page data
if (result)
- result = (sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData);
// Load partial secret into scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(partialSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(partialSecret);
// Compute secret
if (result)
- result = (sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false);
// Configure slave secret on DS2465
- if (result)
- result = (DS28E15_22_25::computeNextSecret(sensorNode.ds2465, pageData, sensorNode.authData.pageNum, partialSecret, sensorNode.ds28e15.romId(), sensorNode.ds28e15.manId()) == ISha256MacCoproc::Success);
+ if (result) {
+ const Sha256::SlaveSecretData data = DS28E15::createSlaveSecretData(
+ pageData, sensorNode.authData.pageNum, partialSecret,
+ sensorNode.romId(), sensorNode.manId);
+ result = !sensorNode.ds2465.computeSlaveSecret(data);
+ }
// Enable authentication protection if not set
- if (result && (protectionStatus != desiredProtection))
- result = (sensorNode.ds28e15.writeAuthBlockProtection(sensorNode.ds2465, desiredProtection, protectionStatus) == OneWireSlave::Success);
+ if (result && (protectionStatus != desiredProtection)) {
+ const Sha256::WriteMacData data = DS28E15::createProtectionWriteMacData(
+ desiredProtection, protectionStatus, sensorNode.romId(),
+ sensorNode.manId);
+ Sha256::Hash mac;
+ result = !sensorNode.ds2465.computeWriteMac(data, mac);
+ if (result)
+ result =
+ !sensorNode.ds28e15.writeAuthBlockProtection(desiredProtection, mac);
+ }
// Write initial filter life and set all other segments to default value
- if (result)
- {
- DS28E15_22_25::Segment blankSegment;
+ if (result) {
+ DS28E15::Segment blankSegment;
blankSegment.fill(uint8_t(SensorNode::defaultPaddingByte));
- for (size_t i = 0; i < DS28E15_22_25::segmentsPerPage; i++)
- {
- result = (sensorNode.ds28e15.writeAuthSegment(sensorNode.ds2465, sensorNode.authData.pageNum, i,
- ((i == sensorNode.authData.segmentNum) ? sensorNode.authData.segment : blankSegment),
- DS28E15_22_25::segmentFromPage(i, pageData), false) == OneWireSlave::Success);
-
+ for (int i = 0; i < DS28E15::segmentsPerPage; i++) {
+ const DS28E15::Segment newSegment = (i == sensorNode.authData.segmentNum)
+ ? sensorNode.authData.segment
+ : blankSegment;
+ const std::pair<DS28E15::Page::iterator, DS28E15::Page::iterator>
+ pageSegment = createSegment(pageData.begin(), pageData.end(),
+ DS28E15::Segment::size(), i);
+ DS28E15::Segment oldSegment;
+ std::copy(pageSegment.first, pageSegment.second, oldSegment.begin());
+ const Sha256::WriteMacData data = DS28E15::createSegmentWriteMacData(
+ sensorNode.authData.pageNum, i, newSegment, oldSegment,
+ sensorNode.romId(), sensorNode.manId);
+ Sha256::Hash mac;
+ result = !sensorNode.ds2465.computeWriteMac(data, mac);
+ if (!result)
+ break;
+ result = !sensorNode.ds28e15.writeAuthSegment(sensorNode.authData.pageNum,
+ i, newSegment, mac);
if (!result)
break;
}
}
-
+
// Reload secret with known page values
// Load master secret into scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(masterSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(masterSecret);
// Load master secret
if (result)
- result = (sensorNode.ds28e15.loadSecret(false) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.loadSecret(false);
// Read page data
if (result)
- result = (sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData);
// Write partial secret to scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(partialSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(partialSecret);
// Compute secret
if (result)
- result = (sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false);
// Configure slave secret on DS2465
- if (result)
- result = (DS28E15_22_25::computeNextSecret(sensorNode.ds2465, pageData, sensorNode.authData.pageNum, partialSecret, sensorNode.ds28e15.romId(), sensorNode.ds28e15.manId()) == ISha256MacCoproc::Success);
+ if (result) {
+ const Sha256::SlaveSecretData data = DS28E15::createSlaveSecretData(
+ pageData, sensorNode.authData.pageNum, partialSecret,
+ sensorNode.romId(), sensorNode.manId);
+ result = !sensorNode.ds2465.computeSlaveSecret(data);
+ }
return result;
}
\ No newline at end of file
MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification