MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification

Dependencies:   MaximInterface mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SensorNode.cpp Source File

SensorNode.cpp

00001 /*******************************************************************************
00002 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #include <I2C.h>
00034 #include <MaximInterface/Devices/DS2465.hpp>
00035 #include <MaximInterface/Links/RomCommands.hpp>
00036 #include <MaximInterface/Platforms/mbed/Sleep.hpp>
00037 #include "SensorNode.hpp"
00038 #include "SensorData.hpp"
00039 
00040 #ifdef TARGET_MAX32600
00041 #include <max32600.h>
00042 #include <clkman_regs.h>
00043 #include <tpu_regs.h>
00044 #else
00045 #include <cstdlib>
00046 #endif
00047 
00048 using namespace MaximInterface;
00049 
00050 const ManId SensorNode::manId = {0, 0};
00051 bool SensorNode::rngInitialized = false;
00052 
00053 void SensorNode::initializeRng() {
00054 #ifdef TARGET_MAX32600
00055   // Enable crypto oscillator
00056   MXC_CLKMAN->clk_config |= (MXC_F_CLKMAN_CLK_CONFIG_CRYPTO_ENABLE |
00057                              MXC_F_CLKMAN_CLK_CONFIG_CRYPTO_RESET_N);
00058   // Wait for crypto oscillator stability
00059   while ((MXC_CLKMAN->intfl & MXC_F_CLKMAN_INTFL_CRYPTO_STABLE) !=
00060          MXC_F_CLKMAN_INTFL_CRYPTO_STABLE);
00061   // Disable crypto clock gating
00062   MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_CRYPTO_GATE_N;
00063   // Set PRNG clock to crypto clock
00064   MXC_CLKMAN->crypt_clk_ctrl_2_prng = MXC_CLKMAN->clk_ctrl_10_prng = 1;
00065   // Use dynamic clock gating
00066   MXC_CLKMAN->clk_gate_ctrl2 |=
00067       (1 << MXC_F_CLKMAN_CLK_GATE_CTRL2_TPU_CLK_GATER_POS);
00068 #endif
00069 }
00070 
00071 SensorNode::SensorNode (::mbed::I2C & i2c, uint8_t ds7505_i2c_addr,
00072                        uint8_t max44009_i2c_addr, DS2465 & ds2465)
00073     : initialLux_(1), ds2465(ds2465),
00074       ds28e15(MaximInterface::mbed::Sleep::instance(), ds2465, &skipRom),
00075       ds7505(i2c, ds7505_i2c_addr), max44009(i2c, max44009_i2c_addr) {
00076   if (!rngInitialized) {
00077     initializeRng();
00078     rngInitialized = true;
00079   }
00080 }
00081 
00082 bool SensorNode::initializeSensors() {
00083   return (max44009.read_current_lux(initialLux_) == MAX44009::Success);
00084 }
00085 
00086 bool SensorNode::setSecret() {
00087   // Create constant partial secret
00088   DS28E15::Scratchpad scratchpad;
00089   scratchpad.fill(uint8_t(defaultPaddingByte));
00090   // Calculate secret
00091   const Sha256::SlaveSecretData data = DS28E15::createSlaveSecretData(
00092       DS28E15::Page(), authData.pageNum, scratchpad, romId_, manId);
00093   return !ds2465.computeSlaveSecretWithSwap(data, 0, DS2465::FullPage);
00094 }
00095 
00096 bool SensorNode::checkProvisioned(bool & provisioned) {
00097   DS28E15::BlockProtection protectionStatus;
00098   bool result;
00099 
00100   result = !ds28e15.readBlockProtection(0, protectionStatus);
00101   if (result) {
00102     if (!protectionStatus.noProtection()) {
00103       result = !ds28e15.readSegment(authData.pageNum, authData.segmentNum,
00104                                     authData.segment);
00105       if (result)
00106         provisioned = true;
00107     } else {
00108       provisioned = false;
00109     }
00110   }
00111   return result;
00112 }
00113 
00114 bool SensorNode::checkAuthentic(unsigned int userEntropy) {
00115   DS28E15::Scratchpad challenge;
00116   DS28E15::Page pageData;
00117 
00118   // Read page data
00119   if (ds28e15.readPage(authData.pageNum, pageData))
00120     return false;
00121 
00122   // Create random challenge
00123   // Use hardare RNG on MAX32600
00124 #ifdef TARGET_MAX32600
00125   MXC_TPU->prng_user_entropy = userEntropy;
00126 #else
00127   std::srand(userEntropy);
00128 #endif
00129   for (size_t i = 0; i < challenge.size(); i++) {
00130 #ifdef TARGET_MAX32600
00131     challenge[i] = MXC_TPU->prng_rnd_num;
00132 #else
00133     challenge[i] = std::rand();
00134 #endif
00135   }
00136 
00137   // Write challenge to scratchpad
00138   if (ds28e15.writeScratchpad(challenge))
00139     return false;
00140   // Have device compute MAC
00141   Sha256::Hash nodeMac;
00142   if (ds28e15.computeReadPageMac(0, false, nodeMac))
00143     return false;
00144   // Compute expected MAC
00145   const Sha256::AuthMacData controllerMacData = DS28E15::createAuthMacData(
00146       pageData, authData.pageNum, challenge, romId_, manId);
00147   Sha256::Hash controllerMac;
00148   if (ds2465.computeAuthMac(controllerMacData, controllerMac))
00149     return false;
00150   // Check if authentic
00151   return (nodeMac == controllerMac);
00152 }
00153 
00154 bool SensorNode::readSensorData(SensorData & sensorData) {
00155   bool result;
00156   int8_t temp;
00157 
00158   // Read temperature sensor
00159   result = (ds7505.read_current_temp(temp) == DS7505::Success);
00160 
00161   if (result) {
00162     sensorData.temp = temp;
00163 
00164     // Read light sensor
00165     double currentLux;
00166     result = (max44009.read_current_lux(currentLux) == MAX44009::Success);
00167     if (result) {
00168       // Convert lux to remaining filter life
00169       sensorData.filterLife =
00170           static_cast<uint8_t>((currentLux / initialLux_) * 100);
00171     }
00172   }
00173 
00174   return result;
00175 }
00176 
00177 bool SensorNode::checkAndWriteAuthData(SensorData & sensorData) {
00178   bool result = true;
00179 
00180   if (sensorData.filterLife > authData.filterLife()) {
00181     sensorData.filterLife = authData.filterLife();
00182   } else if (sensorData.filterLife < authData.filterLife()) {
00183     AuthData newAuthData = authData;
00184     newAuthData.filterLife() = sensorData.filterLife;
00185     const Sha256::WriteMacData macData = DS28E15::createSegmentWriteMacData(
00186         authData.pageNum, authData.segmentNum, newAuthData.segment,
00187         authData.segment, romId_, manId);
00188     Sha256::Hash mac;
00189     result = !ds2465.computeWriteMac(macData, mac);
00190     if (result)
00191       result = !ds28e15.writeAuthSegment(authData.pageNum, authData.segmentNum,
00192                                          newAuthData.segment, mac);
00193     if (result)
00194       authData = newAuthData;
00195   }
00196 
00197   return result;
00198 }
00199 
00200 SensorNode::State  SensorNode::detect(unsigned int userEntropy) {
00201   bool provisioned;
00202 
00203   ds2465.setSpeed(DS2465::OverdriveSpeed);
00204 
00205   if (readRom(ds2465, romId_))
00206     return UnableToCommunicate;
00207 
00208   if (!checkProvisioned(provisioned))
00209     return UnableToCommunicate;
00210 
00211   if (!provisioned)
00212     return NotProvisioned;
00213 
00214   if (!setSecret())
00215     return UnableToCommunicate;
00216 
00217   if (!checkAuthentic(userEntropy))
00218     return NotAuthentic;
00219 
00220   if (!initializeSensors())
00221     return UnableToCommunicate;
00222 
00223   return Authentic;
00224 }
00225 
00226 SensorNode::State 
00227 SensorNode::authenticatedReadSensorData(unsigned int userEntropy,
00228                                         SensorData & sensorData) {
00229   ds2465.setSpeed(DS2465::OverdriveSpeed);
00230 
00231   if (!setSecret())
00232     return UnableToCommunicate;
00233 
00234   if (!checkAuthentic(userEntropy))
00235     return NotAuthentic;
00236 
00237   if (!readSensorData(sensorData))
00238     return UnableToCommunicate;
00239 
00240   if (!checkAndWriteAuthData(sensorData))
00241     return NotAuthentic;
00242 
00243   return Authentic;
00244 }