Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28E16.hpp
00001 /******************************************************************************* 00002 * Copyright (C) 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 #ifndef MaximInterfaceDevices_DS28E16_hpp 00034 #define MaximInterfaceDevices_DS28E16_hpp 00035 00036 #include <stdint.h> 00037 #include <MaximInterfaceCore/Algorithm.hpp> 00038 #include <MaximInterfaceCore/array_span.hpp> 00039 #include <MaximInterfaceCore/FlagSet.hpp> 00040 #include <MaximInterfaceCore/RomId.hpp> 00041 #include <MaximInterfaceCore/RunCommand.hpp> 00042 #include <MaximInterfaceCore/system_error.hpp> 00043 #include "Config.hpp" 00044 00045 namespace MaximInterfaceDevices { 00046 00047 class DS28E16 { 00048 public: 00049 /// Device command results. 00050 enum ErrorValue { 00051 InvalidOperationError = 0x55, 00052 InvalidParameterError = 0x77, 00053 InvalidSequenceError = 0x33, 00054 InternalError = 0x22, 00055 DeviceDisabledError = 0x88, 00056 AuthenticationError = 0x100, 00057 InvalidResponseError ///< Command response does not match expected format. 00058 }; 00059 00060 /// @name Device memory pages 00061 /// @{ 00062 00063 static const int decrementCounterPage = 2; 00064 static const int masterSecretPage = 3; 00065 00066 /// @} 00067 00068 static const int memoryPages = 4; 00069 00070 /// Holds a device memory page. 00071 typedef Core::array_span<uint_least8_t, 16> Page; 00072 00073 /// Holds a Challenge, Partial Secret, or HMAC. 00074 typedef Core::array_span<uint_least8_t, 32> DoublePage; 00075 00076 /// Holds a password used to disable the device. 00077 typedef Core::array_span<uint_least8_t, 2> DisableDevicePassword; 00078 00079 // Format page authentication input data. 00080 class PageAuthenticationData; 00081 00082 // Format compute secret input data. 00083 class ComputeSecretData; 00084 00085 /// Page protection types. 00086 enum PageProtectionType { 00087 RP = 0x01, ///< Read protection. 00088 WP = 0x02, ///< Write protection. 00089 DC = 0x08 ///< Decrement counter. 00090 }; 00091 typedef Core::FlagSet<PageProtectionType, 4> PageProtection; 00092 00093 struct Status { 00094 typedef Core::array_span<PageProtection, memoryPages> PageProtectionList; 00095 00096 PageProtectionList::array pageProtection; 00097 uint_least8_t manId; 00098 uint_least8_t deviceVersion; 00099 }; 00100 00101 explicit DS28E16(const Core::RunCommand & runCommand) 00102 : doRunCommand(runCommand) {} 00103 00104 void setRunCommand(const Core::RunCommand & runCommand) { 00105 doRunCommand = runCommand; 00106 } 00107 00108 /// @brief Write memory with no protection. 00109 /// @param pageNum Number of page to write. 00110 /// @param page Data to write. 00111 MaximInterfaceDevices_EXPORT Core::Result<void> 00112 writeMemory(int pageNum, Page::const_span page); 00113 00114 /// @brief Read memory with no protection. 00115 /// @param pageNum Number of page to read. 00116 /// @returns Data that was read. 00117 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00118 readMemory(int pageNum) const; 00119 00120 /// @brief Reads the current status of the device. 00121 /// @returns Status that was read. 00122 MaximInterfaceDevices_EXPORT Core::Result<Status> readStatus() const; 00123 00124 /// @brief Set the protection settings of a page. 00125 /// @param pageNum Number of page to write. 00126 /// @param protection Protection to write. 00127 MaximInterfaceDevices_EXPORT Core::Result<void> 00128 setPageProtection(int pageNum, const PageProtection & protection); 00129 00130 /// @brief Compute and read page authentication with HMAC. 00131 /// @param pageNum Number of page to authenticate. 00132 /// @param anonymous True to disable use of ROM ID in computation. 00133 /// @param challenge Random challenge used to prevent replay attacks. 00134 /// @returns Computed page HMAC. 00135 MaximInterfaceDevices_EXPORT Core::Result<DoublePage::array> 00136 computeAndReadPageAuthentication(int pageNum, bool anonymous, 00137 DoublePage::const_span challenge) const; 00138 00139 /// Decrement the decrement-only counter. 00140 MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter(); 00141 00142 /// Set password that will be subsequently used to disable the device. 00143 MaximInterfaceDevices_EXPORT Core::Result<void> 00144 setDisableDevicePassword(DisableDevicePassword::const_span password); 00145 00146 /// @brief Lock-out all disable functionality for the device. 00147 /// @note Only allowed prior to setting password. 00148 MaximInterfaceDevices_EXPORT Core::Result<void> lockOutDisableDevice(); 00149 00150 /// Permanently disable the device. 00151 MaximInterfaceDevices_EXPORT Core::Result<void> 00152 disableDevice(DisableDevicePassword::const_span password); 00153 00154 /// @brief 00155 /// Compute a derivative secret for authentication from the Master Secret. 00156 /// @param bindingDataPageNum Page number for Binding Data. 00157 /// @param constantBindingData 00158 /// Use constant Binding Data instead of Binding Data from the selected page. 00159 /// @param anonymous True to disable use of ROM ID in computation. 00160 /// @param partialSecret Partial secret to use in computation. 00161 /// @note 00162 /// This command should be executed prior to the 00163 /// Compute and Read Page Authentication command. 00164 MaximInterfaceDevices_EXPORT Core::Result<void> 00165 computeSecret(int bindingDataPageNum, bool constantBindingData, 00166 bool anonymous, DoublePage::const_span partialSecret); 00167 00168 MaximInterfaceDevices_EXPORT static const Core::error_category & 00169 errorCategory(); 00170 00171 protected: 00172 MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> > 00173 runCommand(Core::span<const uint_least8_t> request, int delayTime, 00174 Core::span<uint_least8_t> response) const; 00175 00176 MaximInterfaceDevices_EXPORT Core::Result<void> 00177 runCommand(Core::span<const uint_least8_t> request, int delayTime); 00178 00179 private: 00180 enum DisableDeviceOperation { 00181 SetDisableDevicePassword = 0x0F, 00182 LockOutDisableDevice = 0x05, 00183 DisableDevice = 0x00 00184 }; 00185 00186 Core::Result<void> disableDevice(DisableDeviceOperation operation, 00187 DisableDevicePassword::const_span password); 00188 00189 Core::RunCommand doRunCommand; 00190 }; 00191 00192 } // namespace MaximInterfaceDevices 00193 namespace MaximInterfaceCore { 00194 00195 template <> 00196 struct is_error_code_enum<MaximInterfaceDevices::DS28E16::ErrorValue> 00197 : true_type {}; 00198 00199 } // namespace MaximInterfaceCore 00200 namespace MaximInterfaceDevices { 00201 00202 inline Core::error_code make_error_code(DS28E16::ErrorValue e) { 00203 return Core::error_code(e, DS28E16::errorCategory()); 00204 } 00205 00206 /// Format page authentication input data. 00207 class DS28E16::PageAuthenticationData { 00208 public: 00209 typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + 00210 DoublePage::size + 3> 00211 Result; 00212 00213 PageAuthenticationData() : result_() {} 00214 00215 /// Formatted data result. 00216 Result::const_span result() const { return result_; } 00217 00218 /// @name ROM ID 00219 /// @brief 1-Wire ROM ID of the device. 00220 /// @{ 00221 00222 /// Get mutable ROM ID. 00223 Core::RomId::span romId() { 00224 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00225 } 00226 00227 /// Get immutable ROM ID. 00228 Core::RomId::const_span romId() const { 00229 return const_cast<PageAuthenticationData &>(*this).romId(); 00230 } 00231 00232 /// Set ROM ID. 00233 PageAuthenticationData & setRomId(Core::RomId::const_span romId) { 00234 copy(romId, this->romId()); 00235 return *this; 00236 } 00237 00238 /// Set ROM ID for use in anonymous mode. 00239 MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); 00240 00241 /// @} 00242 00243 /// @name Page 00244 /// @brief Data from a device memory page. 00245 /// @{ 00246 00247 /// Get mutable page. 00248 Page::span page() { 00249 return make_span(result_).subspan<pageIdx, Page::size>(); 00250 } 00251 00252 /// Get immutable page. 00253 Page::const_span page() const { 00254 return const_cast<PageAuthenticationData &>(*this).page(); 00255 } 00256 00257 /// Set page. 00258 PageAuthenticationData & setPage(Page::const_span page) { 00259 copy(page, this->page()); 00260 return *this; 00261 } 00262 00263 /// @} 00264 00265 /// @name Challenge. 00266 /// @brief Random challenge used to prevent replay attacks. 00267 /// @{ 00268 00269 /// Get mutable Challenge. 00270 DoublePage::span challenge() { 00271 return make_span(result_).subspan<challengeIdx, DoublePage::size>(); 00272 } 00273 00274 /// Get immutable Challenge. 00275 DoublePage::const_span challenge() const { 00276 return const_cast<PageAuthenticationData &>(*this).challenge(); 00277 } 00278 00279 /// Set Challenge. 00280 PageAuthenticationData & setChallenge(DoublePage::const_span challenge) { 00281 copy(challenge, this->challenge()); 00282 return *this; 00283 } 00284 00285 /// @} 00286 00287 /// @name Page number 00288 /// @brief Number of the page to use data from. 00289 /// @{ 00290 00291 /// Get page number. 00292 int pageNum() const { return result_[pageNumIdx]; } 00293 00294 /// Set page number. 00295 PageAuthenticationData & setPageNum(int pageNum) { 00296 result_[pageNumIdx] = pageNum; 00297 return *this; 00298 } 00299 00300 /// @} 00301 00302 /// @name MAN ID 00303 /// @brief Manufacturer ID of the device. 00304 /// @{ 00305 00306 /// Get mutable MAN ID. 00307 uint_least8_t & manId() { return result_[manIdIdx]; } 00308 00309 /// Get immutable MAN ID. 00310 uint_least8_t manId() const { 00311 return const_cast<PageAuthenticationData &>(*this).manId(); 00312 } 00313 00314 /// Set MAN ID. 00315 PageAuthenticationData & setManId(uint_least8_t manId) { 00316 this->manId() = manId; 00317 return *this; 00318 } 00319 00320 /// @} 00321 00322 private: 00323 static const size_t romIdIdx = 0; 00324 static const size_t pageIdx = romIdIdx + Core::RomId::size; 00325 static const size_t challengeIdx = pageIdx + 2 * Page::size; 00326 static const size_t pageNumIdx = challengeIdx + DoublePage::size; 00327 static const size_t manIdIdx = pageNumIdx + 1; 00328 00329 Result::array result_; 00330 }; 00331 00332 /// Format compute secret input data. 00333 class DS28E16::ComputeSecretData { 00334 public: 00335 typedef PageAuthenticationData::Result Result; 00336 00337 ComputeSecretData() : data() { 00338 data.setPageNum(0x80 | constantBindingDataMask); 00339 } 00340 00341 /// Formatted data result. 00342 Result::const_span result() const { return data.result(); } 00343 00344 /// @name ROM ID 00345 /// @brief 1-Wire ROM ID of the device. 00346 /// @{ 00347 00348 /// Get mutable ROM ID. 00349 Core::RomId::span romId() { return data.romId(); } 00350 00351 /// Get immutable ROM ID. 00352 Core::RomId::const_span romId() const { return data.romId(); } 00353 00354 /// Set ROM ID. 00355 ComputeSecretData & setRomId(Core::RomId::const_span romId) { 00356 data.setRomId(romId); 00357 return *this; 00358 } 00359 00360 /// @} 00361 00362 /// @name Binding Data 00363 /// @brief Binding Data contained in the selected page. 00364 /// @{ 00365 00366 /// Get mutable Binding Data. 00367 Page::span bindingData() { return data.page(); } 00368 00369 /// Get immutable Binding Data. 00370 Page::const_span bindingData() const { return data.page(); } 00371 00372 /// Set Binding Data. 00373 ComputeSecretData & setBindingData(Page::const_span bindingData) { 00374 data.setPage(bindingData); 00375 return *this; 00376 } 00377 00378 /// @} 00379 00380 /// @name Constant Binding Data 00381 /// @brief 00382 /// Use constant Binding Data instead of Binding Data from the selected page. 00383 /// @{ 00384 00385 /// Get Constant Binding Data. 00386 bool constantBindingData() const { 00387 return (data.pageNum() & constantBindingDataMask) == 00388 constantBindingDataMask; 00389 } 00390 00391 /// Set Constant Binding Data. 00392 MaximInterfaceDevices_EXPORT ComputeSecretData & 00393 setConstantBindingData(bool constantBindingData); 00394 00395 /// @} 00396 00397 /// @name Partial Secret 00398 /// @brief Partial Secret used for customization. 00399 /// @{ 00400 00401 /// Get mutable Partial Secret. 00402 DoublePage::span partialSecret() { return data.challenge(); } 00403 00404 /// Get immutable Partial Secret. 00405 DoublePage::const_span partialSecret() const { return data.challenge(); } 00406 00407 /// Set Partial Secret. 00408 ComputeSecretData & setPartialSecret(DoublePage::const_span partialSecret) { 00409 data.setChallenge(partialSecret); 00410 return *this; 00411 } 00412 00413 /// @} 00414 00415 /// @name Binding Data page number 00416 /// @{ 00417 00418 /// Get Binding Data page number. 00419 int bindingDataPageNum() const { 00420 return data.pageNum() & bindingDataPageNumMask; 00421 } 00422 00423 /// Set Binding Data page number. 00424 ComputeSecretData & setBindingDataPageNum(int bindingDataPageNum) { 00425 data.setPageNum((bindingDataPageNum & bindingDataPageNumMask) | 00426 (data.pageNum() & ~bindingDataPageNumMask)); 00427 return *this; 00428 } 00429 00430 /// @} 00431 00432 /// @name MAN ID 00433 /// @brief Manufacturer ID of the device. 00434 /// @{ 00435 00436 /// Get mutable MAN ID. 00437 uint_least8_t & manId() { return data.manId(); } 00438 00439 /// Get immutable MAN ID. 00440 uint_least8_t manId() const { return data.manId(); } 00441 00442 /// Set MAN ID. 00443 ComputeSecretData & setManId(uint_least8_t manId) { 00444 data.setManId(manId); 00445 return *this; 00446 } 00447 00448 /// @} 00449 00450 private: 00451 static const unsigned int bindingDataPageNumMask = 0x03; 00452 static const unsigned int constantBindingDataMask = 0x04; 00453 00454 PageAuthenticationData data; 00455 }; 00456 00457 } // namespace MaximInterfaceDevices 00458 00459 #endif
Generated on Tue Jul 12 2022 11:13:11 by 1.7.2