MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification
Dependencies: MaximInterface mbed
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 }
Generated on Wed Jul 13 2022 21:31:03 by 1.7.2