Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28E38.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_DS28E38_hpp 00034 #define MaximInterfaceDevices_DS28E38_hpp 00035 00036 #include <stdint.h> 00037 #include <MaximInterfaceCore/Algorithm.hpp> 00038 #include <MaximInterfaceCore/array_span.hpp> 00039 #include <MaximInterfaceCore/Ecc256.hpp> 00040 #include <MaximInterfaceCore/FlagSet.hpp> 00041 #include <MaximInterfaceCore/ManId.hpp> 00042 #include <MaximInterfaceCore/RomId.hpp> 00043 #include <MaximInterfaceCore/RunCommand.hpp> 00044 #include <MaximInterfaceCore/system_error.hpp> 00045 #include "Config.hpp" 00046 00047 namespace MaximInterfaceDevices { 00048 00049 class DS28E38 { 00050 public: 00051 /// Device command results. 00052 enum ErrorValue { 00053 InvalidOperationError = 0x55, 00054 InvalidParameterError = 0x77, 00055 InvalidSequenceError = 0x33, 00056 InternalError = 0x22, 00057 DeviceDisabledError = 0x88, 00058 InvalidResponseError = 00059 0x100 ///< Command response does not match expected format. 00060 }; 00061 00062 /// @name Device memory pages 00063 /// @{ 00064 00065 static const int decrementCounterPage = 3; 00066 static const int publicKeyXPage = 4; 00067 static const int publicKeyYPage = 5; 00068 static const int privateKeyPage = 6; 00069 00070 /// @} 00071 00072 static const int memoryPages = 7; 00073 00074 /// Holds a device memory page. 00075 typedef Core::array_span<uint_least8_t, 32> Page; 00076 00077 // Format page authentication input data. 00078 class PageAuthenticationData; 00079 00080 /// Page protection types. 00081 enum PageProtectionType { 00082 RP = 0x01, ///< Read protection. 00083 WP = 0x02, ///< Write protection. 00084 EM = 0x04, ///< EPROM emulation mode. 00085 DC = 0x08, ///< Decrement counter. 00086 PF = 0x10 ///< PUF used as private key. 00087 }; 00088 typedef Core::FlagSet<PageProtectionType, 5> PageProtection; 00089 00090 struct Status { 00091 enum EntropyHealthTestStatus { 00092 TestNotPerformed = 0xFF, 00093 EntropyHealthy = 0xAA, 00094 EntropyNotHealthy = 0xDD 00095 }; 00096 00097 typedef Core::array_span<PageProtection, memoryPages> PageProtectionList; 00098 typedef Core::array_span<uint_least8_t, 2> RomVersion; 00099 00100 PageProtectionList::array pageProtection; 00101 Core::ManId::array manId; 00102 RomVersion::array romVersion; 00103 EntropyHealthTestStatus entropyHealthTestStatus; 00104 }; 00105 00106 explicit DS28E38(const Core::RunCommand & runCommand) 00107 : doRunCommand(runCommand) {} 00108 00109 void setRunCommand(const Core::RunCommand & runCommand) { 00110 doRunCommand = runCommand; 00111 } 00112 00113 /// @brief Write memory with no protection. 00114 /// @param pageNum Number of page to write. 00115 /// @param page Data to write. 00116 MaximInterfaceDevices_EXPORT Core::Result<void> 00117 writeMemory(int pageNum, Page::const_span page); 00118 00119 /// @brief Read memory with no protection. 00120 /// @param pageNum Number of page to read. 00121 /// @returns Data that was read. 00122 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00123 readMemory(int pageNum) const; 00124 00125 /// @brief 00126 /// Reads the current status of the device and optionally performs an 00127 /// entropy health test. 00128 /// @param entropyHealthTest True to perform an entropy health test. 00129 /// @returns status Status that was read. 00130 MaximInterfaceDevices_EXPORT Core::Result<Status> 00131 readStatus(bool entropyHealthTest) const; 00132 00133 /// @brief Set the protection settings of a page. 00134 /// @param pageNum Number of page to write. 00135 /// @param protection Protection to write. 00136 MaximInterfaceDevices_EXPORT Core::Result<void> 00137 setPageProtection(int pageNum, const PageProtection & protection); 00138 00139 /// @brief Compute and read page authentication with ECDSA. 00140 /// @param pageNum Number of page to authenticate. 00141 /// @param anonymous True to disable use of ROM ID in computation. 00142 /// @param challenge Random challenge used to prevent replay attacks. 00143 /// @returns Computed page signature. 00144 MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array> 00145 computeAndReadPageAuthentication(int pageNum, bool anonymous, 00146 Page::const_span challenge) const; 00147 00148 /// Decrement the decrement-only counter. 00149 MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter(); 00150 00151 /// Permanently disable the device. 00152 MaximInterfaceDevices_EXPORT Core::Result<void> disableDevice(); 00153 00154 /// @brief Generate a new ECDSA public key from an existing private key. 00155 /// @param privateKeyPuf True if PUF is used as the private key. 00156 /// @param writeProtectEnable True to lock the key against further writes. 00157 MaximInterfaceDevices_EXPORT Core::Result<void> 00158 generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable); 00159 00160 /// @brief Read a block of random data from the RNG. 00161 /// @param[out] data Random data from RNG with length from 1 to 64. 00162 MaximInterfaceDevices_EXPORT Core::Result<void> 00163 readRng(Core::span<uint_least8_t> data) const; 00164 00165 MaximInterfaceDevices_EXPORT static const Core::error_category & 00166 errorCategory(); 00167 00168 protected: 00169 MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> > 00170 runCommand(Core::span<const uint_least8_t> request, int delayTime, 00171 Core::span<uint_least8_t> response) const; 00172 00173 MaximInterfaceDevices_EXPORT Core::Result<void> 00174 runCommand(Core::span<const uint_least8_t> request, int delayTime); 00175 00176 private: 00177 Core::RunCommand doRunCommand; 00178 }; 00179 00180 } // namespace MaximInterfaceDevices 00181 namespace MaximInterfaceCore { 00182 00183 template <> 00184 struct is_error_code_enum<MaximInterfaceDevices::DS28E38::ErrorValue> 00185 : true_type {}; 00186 00187 } // namespace MaximInterfaceCore 00188 namespace MaximInterfaceDevices { 00189 00190 inline Core::error_code make_error_code(DS28E38::ErrorValue e) { 00191 return Core::error_code(e, DS28E38::errorCategory()); 00192 } 00193 00194 /// Format page authentication input data. 00195 class DS28E38::PageAuthenticationData { 00196 public: 00197 typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + 00198 1 + Core::ManId::size> 00199 Result; 00200 00201 PageAuthenticationData() : result_() {} 00202 00203 /// Formatted data result. 00204 Result::const_span result() const { return result_; } 00205 00206 /// @name ROM ID 00207 /// @brief 1-Wire ROM ID of the device. 00208 /// @{ 00209 00210 /// Get mutable ROM ID. 00211 Core::RomId::span romId() { 00212 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00213 } 00214 00215 /// Get immutable ROM ID. 00216 Core::RomId::const_span romId() const { 00217 return const_cast<PageAuthenticationData &>(*this).romId(); 00218 } 00219 00220 /// Set ROM ID. 00221 PageAuthenticationData & setRomId(Core::RomId::const_span romId) { 00222 copy(romId, this->romId()); 00223 return *this; 00224 } 00225 00226 /// Set ROM ID for use in anonymous mode. 00227 MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); 00228 00229 /// @} 00230 00231 /// @name Page 00232 /// @brief Data from a device memory page. 00233 /// @{ 00234 00235 /// Get mutable page. 00236 Page::span page() { 00237 return make_span(result_).subspan<pageIdx, Page::size>(); 00238 } 00239 00240 /// Get immutable page. 00241 Page::const_span page() const { 00242 return const_cast<PageAuthenticationData &>(*this).page(); 00243 } 00244 00245 /// Set page. 00246 PageAuthenticationData & setPage(Page::const_span page) { 00247 copy(page, this->page()); 00248 return *this; 00249 } 00250 00251 /// @} 00252 00253 /// @name Challenge 00254 /// @brief Random challenge used to prevent replay attacks. 00255 /// @{ 00256 00257 /// Get mutable Challenge. 00258 Page::span challenge() { 00259 return make_span(result_).subspan<challengeIdx, Page::size>(); 00260 } 00261 00262 /// Get immutable Challenge. 00263 Page::const_span challenge() const { 00264 return const_cast<PageAuthenticationData &>(*this).challenge(); 00265 } 00266 00267 /// Set Challenge. 00268 PageAuthenticationData & setChallenge(Page::const_span challenge) { 00269 copy(challenge, this->challenge()); 00270 return *this; 00271 } 00272 00273 /// @} 00274 00275 /// @name Page number 00276 /// @brief Number of the page to use data from. 00277 /// @{ 00278 00279 /// Get page number. 00280 int pageNum() const { return result_[pageNumIdx]; } 00281 00282 /// Set page number. 00283 PageAuthenticationData & setPageNum(int pageNum) { 00284 result_[pageNumIdx] = pageNum; 00285 return *this; 00286 } 00287 00288 /// @} 00289 00290 /// @name MAN ID 00291 /// @brief Manufacturer ID of the device. 00292 /// @{ 00293 00294 /// Get mutable MAN ID. 00295 Core::ManId::span manId() { 00296 return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); 00297 } 00298 00299 /// Get immutable MAN ID. 00300 Core::ManId::const_span manId() const { 00301 return const_cast<PageAuthenticationData &>(*this).manId(); 00302 } 00303 00304 /// Set MAN ID. 00305 PageAuthenticationData & setManId(Core::ManId::const_span manId) { 00306 copy(manId, this->manId()); 00307 return *this; 00308 } 00309 00310 /// @} 00311 00312 private: 00313 static const size_t romIdIdx = 0; 00314 static const size_t pageIdx = romIdIdx + Core::RomId::size; 00315 static const size_t challengeIdx = pageIdx + Page::size; 00316 static const size_t pageNumIdx = challengeIdx + Page::size; 00317 static const size_t manIdIdx = pageNumIdx + 1; 00318 00319 Result::array result_; 00320 }; 00321 00322 } // namespace MaximInterfaceDevices 00323 00324 #endif
Generated on Tue Jul 12 2022 11:13:12 by 1.7.2