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