Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28E39.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_DS28E39_hpp 00034 #define MaximInterfaceDevices_DS28E39_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 DS28E39 { 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 AuthenticationError = 0x100, 00059 InvalidResponseError ///< Command response does not match expected format. 00060 }; 00061 00062 /// @name Device memory pages 00063 /// @{ 00064 00065 static const int decrementCounterPage = 4; 00066 static const int authorityPublicKeyXPage = 5; 00067 static const int authorityPublicKeyYPage = 6; 00068 static const int writePublicKeyXPage = 7; 00069 static const int writePublicKeyYPage = 8; 00070 00071 /// @} 00072 00073 static const int memoryPages = 9; 00074 00075 /// Holds a device memory page. 00076 typedef Core::array_span<uint_least8_t, 32> Page; 00077 00078 // Format page authentication input data. 00079 class PageAuthenticationData; 00080 00081 // Format authenticated write input data. 00082 class WriteAuthenticationData; 00083 00084 /// Page protection types. 00085 enum PageProtectionType { 00086 RP = 0x01, ///< Read protection. 00087 WP = 0x02, ///< Write protection. 00088 EM = 0x04, ///< EPROM emulation mode. 00089 DC = 0x08, ///< Decrement counter. 00090 ECW = 0x10 ///< Authenticated write. 00091 }; 00092 typedef Core::FlagSet<PageProtectionType, 5> PageProtection; 00093 00094 struct Status { 00095 enum EntropyHealthTestStatus { 00096 TestNotPerformed = 0xFF, 00097 EntropyHealthy = 0xAA, 00098 EntropyNotHealthy = 0xDD 00099 }; 00100 00101 typedef Core::array_span<PageProtection, memoryPages - 2> 00102 PageProtectionList; 00103 00104 typedef Core::array_span<uint_least8_t, 2> RomVersion; 00105 00106 PageProtectionList::array pageProtection; 00107 Core::ManId::array manId; 00108 RomVersion::array romVersion; 00109 EntropyHealthTestStatus entropyHealthTestStatus; 00110 }; 00111 00112 explicit DS28E39(const Core::RunCommand & runCommand) 00113 : doRunCommand(runCommand) {} 00114 00115 void setRunCommand(const Core::RunCommand & runCommand) { 00116 doRunCommand = runCommand; 00117 } 00118 00119 /// @brief Write memory with no protection. 00120 /// @param pageNum Number of page to write. 00121 /// @param page Data to write. 00122 MaximInterfaceDevices_EXPORT Core::Result<void> 00123 writeMemory(int pageNum, Page::const_span page); 00124 00125 /// @brief Read memory with no protection. 00126 /// @param pageNum Number of page to read. 00127 /// @returns Data that was read. 00128 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00129 readMemory(int pageNum) const; 00130 00131 /// @brief 00132 /// Reads the current status of the device and optionally performs an 00133 /// entropy health test. 00134 /// @param entropyHealthTest True to perform an entropy health test. 00135 /// @returns Status that was read. 00136 MaximInterfaceDevices_EXPORT Core::Result<Status> 00137 readStatus(bool entropyHealthTest) const; 00138 00139 /// @brief Set the protection settings of a page. 00140 /// @param pageNum Number of page to write. 00141 /// @param protection Protection to write. 00142 MaximInterfaceDevices_EXPORT Core::Result<void> 00143 setPageProtection(int pageNum, const PageProtection & protection); 00144 00145 /// @brief Compute and read page authentication with ECDSA. 00146 /// @param pageNum Number of page to authenticate. 00147 /// @param anonymous True to disable use of ROM ID in computation. 00148 /// @param challenge Random challenge used to prevent replay attacks. 00149 /// @returns Computed page signature. 00150 MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array> 00151 computeAndReadPageAuthentication(int pageNum, bool anonymous, 00152 Page::const_span challenge) const; 00153 00154 /// Decrement the decrement-only counter. 00155 MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter(); 00156 00157 /// Permanently disable the device. 00158 MaximInterfaceDevices_EXPORT Core::Result<void> disableDevice(); 00159 00160 /// @brief Generate the device's ECDSA public key from the PUF private key. 00161 /// @returns Device Public Key 00162 MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::PublicKey::array> 00163 readDevicePublicKey() const; 00164 00165 /// @brief Read a block of random data from the RNG. 00166 /// @param[out] data Random data from RNG with length from 1 to 64. 00167 MaximInterfaceDevices_EXPORT Core::Result<void> 00168 readRng(Core::span<uint_least8_t> data) const; 00169 00170 /// @brief 00171 /// Authenticate a public key for authenticated writes using the 00172 /// Authority Public Key. 00173 /// @param certificate 00174 /// Certificate to use for authentication of the Write Public Key. 00175 /// @param customization 00176 /// Certificate customization with length from 1 to 32. 00177 MaximInterfaceDevices_EXPORT Core::Result<void> 00178 authenticatePublicKey(Core::Ecc256::Signature::const_span certificate, 00179 Core::span<const uint_least8_t> customization); 00180 00181 /// @brief Write with ECDSA authentication using the Write Public Key. 00182 /// @param pageNum Number of page to write. 00183 /// @param page Data to write. 00184 /// @param signature Signature to use for authentication of page data. 00185 MaximInterfaceDevices_EXPORT Core::Result<void> 00186 authenticatedWriteMemory(int pageNum, Page::const_span page, 00187 Core::Ecc256::Signature::const_span signature); 00188 00189 MaximInterfaceDevices_EXPORT static const Core::error_category & 00190 errorCategory(); 00191 00192 protected: 00193 MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> > 00194 runCommand(Core::span<const uint_least8_t> request, int delayTime, 00195 Core::span<uint_least8_t> response) const; 00196 00197 MaximInterfaceDevices_EXPORT Core::Result<void> 00198 runCommand(Core::span<const uint_least8_t> request, int delayTime); 00199 00200 private: 00201 Core::RunCommand doRunCommand; 00202 }; 00203 00204 } // namespace MaximInterfaceDevices 00205 namespace MaximInterfaceCore { 00206 00207 template <> 00208 struct is_error_code_enum<MaximInterfaceDevices::DS28E39::ErrorValue> 00209 : true_type {}; 00210 00211 } // namespace MaximInterfaceCore 00212 namespace MaximInterfaceDevices { 00213 00214 inline Core::error_code make_error_code(DS28E39::ErrorValue e) { 00215 return Core::error_code(e, DS28E39::errorCategory()); 00216 } 00217 00218 /// Format page authentication input data. 00219 class DS28E39::PageAuthenticationData { 00220 public: 00221 typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + 00222 1 + Core::ManId::size> 00223 Result; 00224 00225 PageAuthenticationData() : result_() {} 00226 00227 /// Formatted data result. 00228 Result::const_span result() const { return result_; } 00229 00230 /// @name ROM ID 00231 /// @brief 1-Wire ROM ID of the device. 00232 /// @{ 00233 00234 /// Get mutable ROM ID. 00235 Core::RomId::span romId() { 00236 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00237 } 00238 00239 /// Get immutable ROM ID. 00240 Core::RomId::const_span romId() const { 00241 return const_cast<PageAuthenticationData &>(*this).romId(); 00242 } 00243 00244 /// Set ROM ID. 00245 PageAuthenticationData & setRomId(Core::RomId::const_span romId) { 00246 copy(romId, this->romId()); 00247 return *this; 00248 } 00249 00250 /// Set ROM ID for use in anonymous mode. 00251 MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); 00252 00253 /// @} 00254 00255 /// @name Page 00256 /// @brief Data from a device memory page. 00257 /// @{ 00258 00259 /// Get mutable page. 00260 Page::span page() { 00261 return make_span(result_).subspan<pageIdx, Page::size>(); 00262 } 00263 00264 /// Get immutable page. 00265 Page::const_span page() const { 00266 return const_cast<PageAuthenticationData &>(*this).page(); 00267 } 00268 00269 /// Set page. 00270 PageAuthenticationData & setPage(Page::const_span page) { 00271 copy(page, this->page()); 00272 return *this; 00273 } 00274 00275 /// @} 00276 00277 /// @name Challenge 00278 /// @brief Random challenge used to prevent replay attacks. 00279 /// @{ 00280 00281 /// Get mutable Challenge. 00282 Page::span challenge() { 00283 return make_span(result_).subspan<challengeIdx, Page::size>(); 00284 } 00285 00286 /// Get immutable Challenge. 00287 Page::const_span challenge() const { 00288 return const_cast<PageAuthenticationData &>(*this).challenge(); 00289 } 00290 00291 /// Set Challenge. 00292 PageAuthenticationData & setChallenge(Page::const_span challenge) { 00293 copy(challenge, this->challenge()); 00294 return *this; 00295 } 00296 00297 /// @} 00298 00299 /// @name Page number 00300 /// @brief Number of the page to use data from. 00301 /// @{ 00302 00303 /// Get page number. 00304 int pageNum() const { return result_[pageNumIdx]; } 00305 00306 /// Set page number. 00307 PageAuthenticationData & setPageNum(int pageNum) { 00308 result_[pageNumIdx] = pageNum; 00309 return *this; 00310 } 00311 00312 /// @} 00313 00314 /// @name MAN ID 00315 /// @brief Manufacturer ID of the device. 00316 /// @{ 00317 00318 /// Get mutable MAN ID. 00319 Core::ManId::span manId() { 00320 return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); 00321 } 00322 00323 /// Get immutable MAN ID. 00324 Core::ManId::const_span manId() const { 00325 return const_cast<PageAuthenticationData &>(*this).manId(); 00326 } 00327 00328 /// Set MAN ID. 00329 PageAuthenticationData & setManId(Core::ManId::const_span manId) { 00330 copy(manId, this->manId()); 00331 return *this; 00332 } 00333 00334 /// @} 00335 00336 private: 00337 static const size_t romIdIdx = 0; 00338 static const size_t pageIdx = romIdIdx + Core::RomId::size; 00339 static const size_t challengeIdx = pageIdx + Page::size; 00340 static const size_t pageNumIdx = challengeIdx + Page::size; 00341 static const size_t manIdIdx = pageNumIdx + 1; 00342 00343 Result::array result_; 00344 }; 00345 00346 /// Format authenticated write input data. 00347 class DS28E39::WriteAuthenticationData { 00348 public: 00349 typedef PageAuthenticationData::Result Result; 00350 00351 WriteAuthenticationData() : data() { setPageNum(0); } 00352 00353 /// Formatted data result. 00354 Result::const_span result() const { return data.result(); } 00355 00356 /// @name ROM ID 00357 /// @brief 1-Wire ROM ID of the device. 00358 /// @{ 00359 00360 /// Get mutable ROM ID. 00361 Core::RomId::span romId() { return data.romId(); } 00362 00363 /// Get immutable ROM ID. 00364 Core::RomId::const_span romId() const { return data.romId(); } 00365 00366 /// Set ROM ID. 00367 WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { 00368 data.setRomId(romId); 00369 return *this; 00370 } 00371 00372 /// @} 00373 00374 /// @name Old page 00375 /// @brief Existing data contained in the page. 00376 /// @{ 00377 00378 /// Get mutable old page. 00379 Page::span oldPage() { return data.page(); } 00380 00381 /// Get immutable old page. 00382 Page::const_span oldPage() const { return data.page(); } 00383 00384 /// Set old page. 00385 WriteAuthenticationData & setOldPage(Page::const_span oldPage) { 00386 data.setPage(oldPage); 00387 return *this; 00388 } 00389 00390 /// @} 00391 00392 /// @name New page 00393 /// @brief New data to write to the page. 00394 /// @{ 00395 00396 /// Get mutable new page. 00397 Page::span newPage() { return data.challenge(); } 00398 00399 /// Get immutable new page. 00400 Page::const_span newPage() const { return data.challenge(); } 00401 00402 /// Set new page. 00403 WriteAuthenticationData & setNewPage(Page::const_span newPage) { 00404 data.setChallenge(newPage); 00405 return *this; 00406 } 00407 00408 /// @} 00409 00410 /// @name Page number 00411 /// @brief Page number for write operation. 00412 /// @{ 00413 00414 /// Get page number. 00415 int pageNum() const { return data.pageNum() & 0x7F; } 00416 00417 /// Set page number. 00418 WriteAuthenticationData & setPageNum(int pageNum) { 00419 data.setPageNum(pageNum | 0x80); 00420 return *this; 00421 } 00422 00423 /// @} 00424 00425 /// @name MAN ID 00426 /// @brief Manufacturer ID of the device. 00427 /// @{ 00428 00429 /// Get mutable MAN ID. 00430 Core::ManId::span manId() { return data.manId(); } 00431 00432 /// Get immutable MAN ID. 00433 Core::ManId::const_span manId() const { return data.manId(); } 00434 00435 /// Set MAN ID. 00436 WriteAuthenticationData & setManId(Core::ManId::const_span manId) { 00437 data.setManId(manId); 00438 return *this; 00439 } 00440 00441 /// @} 00442 00443 private: 00444 PageAuthenticationData data; 00445 }; 00446 00447 } // namespace MaximInterfaceDevices 00448 00449 #endif
Generated on Tue Jul 12 2022 11:13:13 by 1.7.2