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