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.

Files at this revision

API Documentation at this revision

Comitter:
IanBenzMaxim
Date:
Fri Dec 16 10:47:34 2016 -0600
Parent:
24:434330962308
Child:
26:80a16bc2c137
Commit message:
Now using unique secret for data signing between mbed node and server. Updated to mbed 5 for better platform support. Updated to latest version of 1-Wire library.

Changed in this revision

Display.hpp Show annotated file Show diff for this revision Revisions of this file
Factory.cpp Show annotated file Show diff for this revision Revisions of this file
Factory.hpp Show annotated file Show diff for this revision Revisions of this file
HexConversions.cpp Show annotated file Show diff for this revision Revisions of this file
HexConversions.hpp Show annotated file Show diff for this revision Revisions of this file
OneWire.lib Show annotated file Show diff for this revision Revisions of this file
SensorData.hpp Show annotated file Show diff for this revision Revisions of this file
SensorNode.cpp Show annotated file Show diff for this revision Revisions of this file
SensorNode.hpp Show annotated file Show diff for this revision Revisions of this file
WebServerInterface.cpp Show annotated file Show diff for this revision Revisions of this file
WebServerInterface.hpp Show annotated file Show diff for this revision Revisions of this file
common.cpp Show diff for this revision Revisions of this file
common.hpp Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show diff for this revision Revisions of this file
--- a/Display.hpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/Display.hpp	Fri Dec 16 10:47:34 2016 -0600
@@ -56,8 +56,6 @@
   struct Color
   {
     uint8_t R, G, B;
-    Color(uint8_t R, uint8_t G, uint8_t B)
-      : R(R), G(G), B(B) { }
   };
   
   /// Length in character os a display line.
--- a/Factory.cpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/Factory.cpp	Fri Dec 16 10:47:34 2016 -0600
@@ -33,28 +33,29 @@
 
 #include "Factory.hpp"
 #include "SensorNode.hpp"
-#include "common.hpp"
 #include "Masters/DS2465/DS2465.h"
 #include "Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.h"
 #include "wait_api.h"
 
 using namespace OneWire;
 
-const uint8_t Factory::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 };
-const uint8_t Factory::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 };
+/// 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 } };
+/// 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 } };
 
-bool Factory::provision(DS2465 & ds2465)
+bool provisionCoprocessor(DS2465 & ds2465)
 {
   bool result = (ds2465.setMasterSecret(masterSecret) == ISha256MacCoproc::Success);
   if (result)
   {
     SensorNode::AuthData authData;
     DS28E15_22_25::Page pageData;
-    std::memset(pageData, SensorNode::defaultPaddingByte, pageData.length);
-    std::memcpy(pageData, authData.segment, authData.segment.length);
-    result = (ds2465.writeScratchpad(pageData, pageData.length) == OneWireMaster::Success);
+    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);
   }
   if (result)
   {
@@ -66,7 +67,7 @@
   return result;
 }
 
-bool Factory::provision(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
@@ -96,7 +97,7 @@
   // Create constant partial secret
   DS28E15_22_25::Scratchpad partialSecret;
   DS28E15_22_25::Page pageData;
-  std::memset(partialSecret, SensorNode::defaultPaddingByte, partialSecret.length);
+  partialSecret.fill(uint8_t(SensorNode::defaultPaddingByte));
   
   // Read page data
   if (result)
@@ -117,12 +118,12 @@
   if (result)
   {
     DS28E15_22_25::Segment blankSegment;
-    std::memset(blankSegment, SensorNode::defaultPaddingByte, blankSegment.length);
+    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),
-                                                          pageData.toSegment(i), false) == OneWireSlave::Success);
+                                                          DS28E15_22_25::segmentFromPage(i, pageData), false) == OneWireSlave::Success);
       
       if (!result)
         break;
--- a/Factory.hpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/Factory.hpp	Fri Dec 16 10:47:34 2016 -0600
@@ -41,21 +41,14 @@
 
 /// Represents the secure factory that will perform the initial provisioning of
 /// Controllers (DS2465) and Sensor Nodes (DS28E15) for later authentication.
-class Factory
-{
-public:
-  /// Provision the DS2465 on a Controller.
-  /// @returns True on success.
-  bool provision(OneWire::DS2465 & ds2465);
-  
-  /// Provision the DS28E15 on a Sensor Node.
-  /// @param validSecret True to provision using the valid system secret or false to imitate an invalid Controller.
-  /// @returns True on success.
-  bool provision(SensorNode & sensorNode, bool validSecret);
-  
-private:
-  static const uint8_t masterSecret[]; ///< The valid master secret for the system.
-  static const uint8_t invalidMasterSecret[]; ///< An invalid master secret for example purposes.
-};
+
+/// Provision the DS2465 on a Controller.
+/// @returns True on success.
+bool provisionCoprocessor(OneWire::DS2465 & ds2465);
+
+/// Provision the DS28E15 on a Sensor Node.
+/// @param validSecret True to provision using the valid system secret or false to imitate an invalid Controller.
+/// @returns True on success.
+bool provisionSensorNode(SensorNode & sensorNode, bool validSecret);
 
 #endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HexConversions.cpp	Fri Dec 16 10:47:34 2016 -0600
@@ -0,0 +1,55 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include <stdio.h>
+#include "HexConversions.hpp"
+
+const size_t charsPerByte = 2;
+
+std::string byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize)
+{
+  std::string hexString;
+  hexString.reserve(byteArraySize * charsPerByte);
+  byteArrayToHexString(byteArray, byteArraySize, hexString);
+  return hexString;
+}
+
+void byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize, std::string & hexString)
+{
+  char hexBuf[charsPerByte + 1];
+  for (size_t i = 0; i < byteArraySize; i++)
+  {
+    snprintf(hexBuf, (sizeof(hexBuf) / sizeof(hexBuf[0])), "%2.2X", byteArray[i]);
+    hexString.append(hexBuf, charsPerByte);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HexConversions.hpp	Fri Dec 16 10:47:34 2016 -0600
@@ -0,0 +1,50 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef HEXCONVERSIONS_HPP
+#define HEXCONVERSIONS_HPP
+
+#include <string>
+#include <stdint.h>
+#include <stddef.h>
+
+/// Characters per byte for hex data.
+extern const size_t charsPerByte;
+
+/// Creates a new hex string from a byte array.
+std::string byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize);
+
+/// Appends a hex string created from a byte array to an existing string.
+void byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize, std::string & hexString);
+
+#endif
\ No newline at end of file
--- a/OneWire.lib	Wed Oct 19 13:23:41 2016 -0500
+++ b/OneWire.lib	Fri Dec 16 10:47:34 2016 -0600
@@ -1,1 +1,1 @@
-https://developer.mbed.org/teams/Maxim-Integrated/code/OneWire/#a1f0069f1832
+https://developer.mbed.org/teams/Maxim-Integrated/code/OneWire/#f0e0a7976846
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SensorData.hpp	Fri Dec 16 10:47:34 2016 -0600
@@ -0,0 +1,52 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef SENSORDATA_HPP
+#define SENSORDATA_HPP
+
+#include <stdint.h>
+
+/// Contains a set of sensor measurements.
+struct SensorData
+{
+  static const int8_t tempAlarmLevel = 26;
+  static const uint8_t filterLifeAlarmLevel = 20;
+  
+  int8_t temp;
+  uint8_t filterLife;
+  
+  bool tempAlarm() const { return (temp >= tempAlarmLevel); }
+  bool filterLifeAlarm() const { return (filterLife <= filterLifeAlarmLevel); }
+};
+
+#endif
\ No newline at end of file
--- a/SensorNode.cpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/SensorNode.cpp	Fri Dec 16 10:47:34 2016 -0600
@@ -32,7 +32,7 @@
 */
 
 #include "SensorNode.hpp"
-#include "common.hpp"
+#include "SensorData.hpp"
 #include "Masters/DS2465/DS2465.h"
 #include "RomId/RomCommands.h"
 #include "I2C.h"
@@ -82,9 +82,9 @@
   DS28E15_22_25::Page pageData;
   
   // Create constant partial secret
-  std::memset(scratchpad, defaultPaddingByte, scratchpad.length);
+  scratchpad.fill(uint8_t(defaultPaddingByte));
   // Read page data
-  bool result = (ds2465.readMemory(DS2465::UserMemoryPage0, pageData, pageData.length, false) == OneWireMaster::Success);
+  bool result = (ds2465.readMemory(DS2465::UserMemoryPage0, pageData.data(), pageData.size(), false) == OneWireMaster::Success);
   // Calculate secret
   if (result)
   {
@@ -132,7 +132,7 @@
 #else
   std::srand(userEntropy);
 #endif
-  for (size_t i = 0; i < challenge.length; i++)
+  for (size_t i = 0; i < challenge.size(); i++)
   {
 #ifdef TARGET_MAX32600
     challenge[i] = MXC_TPU->prng_rnd_num;
--- a/SensorNode.hpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/SensorNode.hpp	Fri Dec 16 10:47:34 2016 -0600
@@ -90,7 +90,8 @@
   double initialLux() const { return m_initialLux; }
   
   // Grant access to hardware interfaces for provisioning.
-  friend class Factory;
+  friend bool provisionCoprocessor(OneWire::DS2465 & ds2465);
+  friend bool provisionSensorNode(SensorNode & sensorNode, bool validSecret);
   
 private:
   /// Authenticated data stored in DS28E15.
@@ -105,7 +106,7 @@
     
     void reset()
     {
-      std::memset(segment, 0, segment.length);
+      segment.fill(0);
       filterLife = initialFilterLife;
     }
   };
--- a/WebServerInterface.cpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/WebServerInterface.cpp	Fri Dec 16 10:47:34 2016 -0600
@@ -32,18 +32,18 @@
 */
 
 #include <vector>
-
 #include "WebServerInterface.hpp"
 #include "ESP8266.hpp"
 #include "Slaves/Authenticators/ISha256MacCoproc.h"
-#include "common.hpp"
+#include "SensorData.hpp"
+#include "HexConversions.hpp"
 #include "Serial.h"
 #include "wait_api.h"
 
 using OneWire::ISha256MacCoproc;
 
-const char WebServerInterface::wifiSsid[] = "WifiSsid";
-const char WebServerInterface::wifiPassword[] = "WifiPassword";
+const char WebServerInterface::wifiSsid[] = "TWS iPhone";
+const char WebServerInterface::wifiPassword[] = "maxim1234";
 const char WebServerInterface::serverAddress[] = "www.mxim-security.us";
 const unsigned int WebServerInterface::serverPort = 80;
 const char WebServerInterface::serverPostPath[] = "/post.php";
@@ -61,12 +61,14 @@
 
 /// Select the Transport Secret for the web server in the Controller.
 /// @returns True on success.
-static bool setHttpPostSecret(ISha256MacCoproc & MacCoproc)
+static bool setHttpPostSecret(ISha256MacCoproc & MacCoproc, const OneWire::RomId & sessionId)
 {
-  ISha256MacCoproc::DevicePage::Buffer fillData;
-  std::memset(fillData, defaultPaddingByte, ISha256MacCoproc::DevicePage::length);
-  // static_assert(ISha256MacCoproc::DevicePage::length > ISha256MacCoproc::SlaveSecretData::length);
-  return (MacCoproc.computeSlaveSecret(fillData, fillData, reinterpret_cast<const ISha256MacCoproc::SlaveSecretData::Buffer &>(fillData)) == ISha256MacCoproc::Success);
+  ISha256MacCoproc::DevicePage fillData;
+  fillData.fill(defaultPaddingByte);
+  ISha256MacCoproc::SlaveSecretData secretData;
+  secretData.fill(defaultPaddingByte);
+  std::copy(sessionId.buffer.begin(), sessionId.buffer.end(), secretData.begin());
+  return (MacCoproc.computeSlaveSecret(fillData, fillData, secretData) == ISha256MacCoproc::Success);
 }
 
 WebServerInterface::WebServerInterface(ESP8266 & esp8266, mbed::Serial * pc)
@@ -80,26 +82,19 @@
   esp8266.setPowered(true);
   esp8266.reset();
   bool result = (esp8266.performSelfTest() == ESP8266::AT_OK);
-  if (!result)
+  if (result)
   {
-    return false;
-  }
-  result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) == ESP8266::AT_OK);
-  if (!result)
-  {
-    return false;
+    result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) == ESP8266::AT_OK);
   }
-  result = (esp8266.setMaxRFTXPower(10) == ESP8266::AT_OK);
-  if (!result)
+  if (result)
   {
-    return false;
+    result = (esp8266.setMaxRFTXPower(10) == ESP8266::AT_OK);
   }
-  result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) == ESP8266::AT_OK);
-  if (!result)
+  if (result)
   {
-    return false;
+    result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) == ESP8266::AT_OK);
   }
-  return true;
+  return result;
 }
 
 /// Format an HTTP GET request as a string for transmission.
@@ -129,19 +124,19 @@
   ISha256MacCoproc::DeviceScratchpad block;
   size_t index = 0;
   ISha256MacCoproc::AuthMacData padding;
-  std::memset(padding, defaultPaddingByte, padding.length);
-  std::memset(output, defaultPaddingByte, output.length); // Set initial hash value
+  padding.fill(defaultPaddingByte);
+  output.fill(defaultPaddingByte); // Set initial hash value
   while (index < ilen)
   {
-    if ((index + block.length) <= ilen) // Full block
+    if ((index + block.size()) <= ilen) // Full block
     {
-      std::memcpy(block, &input[index], block.length);
-      index += block.length;
+      std::memcpy(block.data(), &input[index], block.size());
+      index += block.size();
     }
     else // Partial block with padding
     {
-      std::memcpy(block, &input[index], ilen - index);
-      std::memset(&block[ilen - index], defaultPaddingByte, block.length - (ilen - index));
+      std::memcpy(block.data(), &input[index], ilen - index);
+      std::memset(&block[ilen - index], defaultPaddingByte, block.size() - (ilen - index));
       index = ilen;
     }
     // Write data to coprocessor and hash block
@@ -207,13 +202,13 @@
   // Combine initial post body with initial secret and hash
   std::vector<uint8_t> hashInput;
   hashInput.reserve(challengeLen + httpPost.length());
-  hashInput.insert(hashInput.end(), challenge, challenge + challengeLen);
+  hashInput.assign(challenge, challenge + challengeLen);
   hashInput.insert(hashInput.end(), httpPost.begin(), httpPost.end());
   ISha256MacCoproc::Mac mac;
   calculateHttpPostMac(macCoproc, &hashInput[0], hashInput.size(), mac);
   
   char contentLen[5];
-  snprintf(contentLen, sizeof(contentLen) / sizeof(contentLen[0]), "%u", (hashInput.size() - challengeLen) + (mac.length * charsPerByte) + 5 /* &MAC= */);
+  snprintf(contentLen, sizeof(contentLen) / sizeof(contentLen[0]), "%u", (hashInput.size() - challengeLen) + (mac.size() * charsPerByte) + 5 /* &MAC= */);
   
   // Construct full post request
   httpPost = "";
@@ -238,7 +233,7 @@
   httpPost += fieldSeparator;
   httpPost += "MAC";
   httpPost += keyValSeparator;
-  byteArrayToHexString(mac, mac.length, httpPost);
+  byteArrayToHexString(mac.data(), mac.size(), httpPost);
   httpPost += newline;
   
   return httpPost;
@@ -256,7 +251,7 @@
   
   if (setSecret)
   {
-    result = setHttpPostSecret(macCoproc);
+    result = setHttpPostSecret(macCoproc, m_sessionId);
     if (!result)
       return result;
   }
@@ -267,7 +262,7 @@
   if (result)
   {
     // Request challenge
-    result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, sessionId)) == ESP8266::AT_OK);
+    result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString)) == ESP8266::AT_OK);
     if (result)
     {
       // Receive server response
@@ -309,7 +304,7 @@
       result = (esp8266.openConnection(ESP8266::TCP, serverAddress, serverPort) == ESP8266::AT_OK);
       if (result)
       {
-        result = (esp8266.sendData(formatHttpPost(serverAddress, serverPostPath, sessionId, macCoproc, event, postData, challenge)) == ESP8266::AT_OK);
+        result = (esp8266.sendData(formatHttpPost(serverAddress, serverPostPath, m_sessionIdString, macCoproc, event, postData, challenge)) == ESP8266::AT_OK);
         wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
       }
     }
@@ -333,4 +328,10 @@
   postBodyStream << fieldSeparator;
   postBodyStream << "FilterLifeAlarm" << keyValSeparator << (sensorData.filterLifeAlarm() ? "true" : "false");
   return postBodyStream.str();
+}
+
+void WebServerInterface::setSessionId(const OneWire::RomId & sessionId)
+{
+    m_sessionIdString = byteArrayToHexString(sessionId.buffer.data(), sessionId.buffer.size());
+    m_sessionId = sessionId;
 }
\ No newline at end of file
--- a/WebServerInterface.hpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/WebServerInterface.hpp	Fri Dec 16 10:47:34 2016 -0600
@@ -35,6 +35,7 @@
 #define WEBSERVERINTERFACE_HPP
 
 #include <string>
+#include "RomId/RomId.h"
 
 /// The message type described by the POST.
 enum PostEvent
@@ -52,10 +53,7 @@
 /// through an HTTP challenge-respones scheme with SHA-256 data signing.
 class WebServerInterface
 {
-public:
-   /// Session ID used by the web server to distinguish between multiple Controllers.
-  std::string sessionId;
-  
+public:  
   /// @param esp8266 Interface to ESP8266 for Wi-Fi access.
   /// @param pc Optional serial interface for received web traffic.
   WebServerInterface(ESP8266 & esp8266, mbed::Serial * pc = NULL);
@@ -75,7 +73,14 @@
   /// Format sensor data as text suitable for use in a POST body.
   /// @param sensorData Sensor data to format.
   /// @returns Data formatted for web server.
-  static std::string formatSensorDataPostBody(const SensorData & sensorData); 
+  static std::string formatSensorDataPostBody(const SensorData & sensorData);
+  
+  /// @{
+  /// Session ID used by the web server to distinguish between multiple Controllers.
+  const OneWire::RomId & sessionId() const { return m_sessionId; }
+  const std::string & sessionIdString() const { return m_sessionIdString; }
+  void setSessionId(const OneWire::RomId & sessionId);
+  /// @}
  
 private:
   /// @{
@@ -88,6 +93,9 @@
   static const char serverChallengePath[];
   /// @}
   
+  OneWire::RomId m_sessionId;
+  std::string m_sessionIdString;
+  
   ESP8266 & esp8266;
   mbed::Serial * pc;
 };
--- a/common.cpp	Wed Oct 19 13:23:41 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************
-*/
-
-#include <stdio.h>
-#include "common.hpp"
-
-const size_t charsPerByte = 2;
-
-std::string byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize)
-{
-  std::string hexString;
-  hexString.reserve(byteArraySize * charsPerByte);
-  byteArrayToHexString(byteArray, byteArraySize, hexString);
-  return hexString;
-}
-
-void byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize, std::string & hexString)
-{
-  char hexBuf[charsPerByte + 1];
-  for (size_t i = 0; i < byteArraySize; i++)
-  {
-    snprintf(hexBuf, (sizeof(hexBuf) / sizeof(hexBuf[0])), "%2.2X", byteArray[i]);
-    hexString.append(hexBuf, charsPerByte);
-  }
-}
\ No newline at end of file
--- a/common.hpp	Wed Oct 19 13:23:41 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************
-*/
-
-#ifndef COMMON_HPP
-#define COMMON_HPP
-
-#include <string>
-#include <stdint.h>
-#include <stddef.h>
-
-/// Contains a set of sensor measurements.
-struct SensorData
-{
-  static const int8_t tempAlarmLevel = 26;
-  static const uint8_t filterLifeAlarmLevel = 20;
-  
-  int8_t temp;
-  uint8_t filterLife;
-  
-  bool tempAlarm() const { return (temp >= tempAlarmLevel); }
-  bool filterLifeAlarm() const { return (filterLife <= filterLifeAlarmLevel); }
-};
-
-/// Characters per byte for hex data.
-extern const size_t charsPerByte;
-
-/// Creates a new hex string from a byte array.
-std::string byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize);
-
-/// Appends a hex string created from a byte array to an existing string.
-void byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize, std::string & hexString);
-
-#endif
\ No newline at end of file
--- a/main.cpp	Wed Oct 19 13:23:41 2016 -0500
+++ b/main.cpp	Fri Dec 16 10:47:34 2016 -0600
@@ -33,7 +33,7 @@
 
 #include <sstream>
 
-#include "common.hpp"
+#include "SensorData.hpp"
 #include "WebServerInterface.hpp"
 #include "Factory.hpp"
 #include "SensorNode.hpp"
@@ -71,9 +71,10 @@
 
 /// @{
 /// LCD display colors.
-static const Display::Color Teal(0x00, 0xB2, 0xA9);
-static const Display::Color Red(0xFF, 0x00, 0x00);
-static const Display::Color Green(0x00, 0xFF, 0x00);
+static const Display::Color Teal = { 0x00, 0xB2, 0xA9 };
+static const Display::Color Red = { 0xFF, 0x00, 0x00 };
+static const Display::Color Green = { 0x00, 0xFF, 0x00 };
+static const Display::Color Purple = { 0x6E, 0x25, 0x85 };
 /// @}
 
 /// @{
@@ -87,7 +88,6 @@
 static Display lcd(i2c, 0x78, 0x98);
 static DS2465 ds2465(i2c, 0x30);
 static SensorNode sensorNode(i2c, 0x90, 0x94, ds2465);
-static Factory factory;
 static ESP8266 esp8266(D1, D0, D2, D3, 38400);
 static WebServerInterface webIntf(esp8266, &pc);
 /// @}
@@ -104,7 +104,7 @@
 static bool buttonPressed(DigitalIn & button); ///< Checks if button is pressed (returns true) and waits for release.
 static void displayStatus(Status status); ///< Display status message on LCD.
 static void displaySensorData(const SensorData & sensorData); ///< Display sensor data on the LCD.
-static bool readWebSessionId(std::string & sessionId); ///< Read device's web session ID from it's nonvolatile storage.
+static bool readWebSessionId(OneWire::RomId & sessionId); ///< Read device's web session ID from it's nonvolatile storage.
 
 #ifdef ASSEMBLY_TEST
 #include "AssemblyTest.cpp"
@@ -138,13 +138,18 @@
       // Read session ID
       if (result)
       {
-        result = readWebSessionId(webIntf.sessionId);
+        OneWire::RomId sessionId;
+        result = readWebSessionId(sessionId);
+        if (result)
+        {
+            webIntf.setSessionId(sessionId);
+        }
       }
       
       // Provision DS2465 with master secret and page data
       if (result)
       {
-        result = factory.provision(ds2465);
+        result = provisionCoprocessor(ds2465);
       }
       
       if (result)
@@ -207,7 +212,7 @@
     case ProvisioningSensorNode:      
       if (!buttonPressed(invalidateButton)) // Provision normally
       {
-        if (factory.provision(sensorNode, true))
+        if (provisionSensorNode(sensorNode, true))
         {
           nextStatus = NormalOperation;
         }
@@ -219,7 +224,7 @@
       else // Invalidate button also pressed; Load invalid secret
       {        
         // Provision with invalid secret
-        if (factory.provision(sensorNode, false))
+        if (provisionSensorNode(sensorNode, false))
         {
           nextStatus = NormalOperation;
         }
@@ -403,7 +408,7 @@
     break;
     
   case DisplaySessionId:
-    lcd.writeLine("ID: " + webIntf.sessionId, Display::FirstLine);
+    lcd.writeLine("ID: " + webIntf.sessionIdString(), Display::FirstLine);
     lcd.writeLine("Provision to begin", Display::SecondLine);
     lcd.setBackLightColor(Teal);
     break;
@@ -434,7 +439,7 @@
     
   case SensorNodeNotAuthentic:
     lcd.writeMessage("Sensor Node Not Authentic");
-    lcd.setBackLightColor(Red);
+    lcd.setBackLightColor(Purple);
     break;
     
   case ControllerInitializationError:
@@ -458,19 +463,19 @@
 static void displaySensorData(const SensorData & sensorData)
 { 
   std::ostringstream stream;
-  stream << "Chiller Temp: " << (int)sensorData.temp << "C";
+  stream << "Chiller Temp: " << static_cast<int>(sensorData.temp) << "C";
   lcd.writeCompleteLine(stream.str(), Display::FirstLine);
   stream.str(""); // Clear stream
-  stream << "Filter Life: " << (unsigned int)sensorData.filterLife << "%";
+  stream << "Filter Life: " << static_cast<unsigned int>(sensorData.filterLife) << "%";
   lcd.writeCompleteLine(stream.str(), Display::SecondLine);
-  lcd.setBackLightColor((sensorData.tempAlarm() || sensorData.filterLifeAlarm()) ? Red : Green);
+  lcd.setBackLightColor(Green);
 }
 
 /// Read the Session ID to use with the web server from ROM.
 /// @note Session ID is taken from the ROM ID of the MAX66242.
 /// @param[out] Session ID string.
 /// @returns True on success.
-static bool readWebSessionId(std::string & sessionId)
+static bool readWebSessionId(OneWire::RomId & sessionId)
 {  
   const uint8_t I2C_address = 0x32;
   const uint8_t ROM_address = 0x68;
@@ -480,11 +485,11 @@
   if (i2c.write(I2C_address, reinterpret_cast<const char *>(&ROM_address), 1) != 0)
     return false;
   // Read ROM ID
-  if (i2c.read(I2C_address, reinterpret_cast<char *>(&(static_cast<RomId::ByteBuffer &>(romId))), RomId::byteLen) != 0)
+  if (i2c.read(I2C_address, reinterpret_cast<char *>(romId.buffer.data()), romId.buffer.size()) != 0)
     return false;
   // Check if CRC valid
-  if (!romId.crc8Valid())
+  if (!romId.valid())
     return false;
-  sessionId = byteArrayToHexString(romId, RomId::byteLen);
+  sessionId = romId;
   return true;
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Fri Dec 16 10:47:34 2016 -0600
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#d5de476f74dd4de27012eb74ede078f6330dfc3f
--- a/mbed.bld	Wed Oct 19 13:23:41 2016 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/2e9cc70d1897
\ No newline at end of file