Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28C40.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_DS28C40_hpp 00034 #define MaximInterfaceDevices_DS28C40_hpp 00035 00036 #include <stdint.h> 00037 #include <utility> 00038 #include <MaximInterfaceCore/Algorithm.hpp> 00039 #include <MaximInterfaceCore/array_span.hpp> 00040 #include <MaximInterfaceCore/Ecc256.hpp> 00041 #include <MaximInterfaceCore/FlagSet.hpp> 00042 #include <MaximInterfaceCore/ManId.hpp> 00043 #include <MaximInterfaceCore/Optional.hpp> 00044 #include <MaximInterfaceCore/RomId.hpp> 00045 #include <MaximInterfaceCore/RunCommand.hpp> 00046 #include <MaximInterfaceCore/system_error.hpp> 00047 #include "Config.hpp" 00048 00049 namespace MaximInterfaceDevices { 00050 00051 class DS28C40 { 00052 public: 00053 /// Device command results. 00054 enum ErrorValue { 00055 InternalError = 0x22, 00056 InvalidSequenceError = 0x33, 00057 InvalidOperationError = 0x55, 00058 InvalidParameterError = 0x77, 00059 DeviceDisabledError = 0x88, 00060 EntropyHealthTestError = 0xDD, 00061 AuthenticationError = 0x100, 00062 InvalidResponseError ///< Command response does not match expected format. 00063 }; 00064 00065 /// @name Device memory pages 00066 /// @{ 00067 00068 static const int publicKeyAxPage = 28; 00069 static const int publicKeyAyPage = 29; 00070 static const int publicKeyBxPage = 30; 00071 static const int publicKeyByPage = 31; 00072 static const int authorityPublicKeyAxPage = 32; 00073 static const int authorityPublicKeyAyPage = 33; 00074 static const int authorityPublicKeyBxPage = 34; 00075 static const int authorityPublicKeyByPage = 35; 00076 static const int privateKeyAPage = 36; 00077 static const int privateKeyBPage = 37; 00078 static const int secretAPage = 38; 00079 static const int secretBPage = 39; 00080 static const int romOptionsPage = 40; 00081 static const int gpioControlPage = 41; 00082 static const int publicKeySxPage = 42; 00083 static const int publicKeySyPage = 43; 00084 00085 /// @} 00086 00087 static const int memoryPages = 44; 00088 static const int protectionBlocks = 9; 00089 00090 /// Key or secret to use for operation. 00091 enum KeySecret { KeySecretA = 0, KeySecretB = 1, KeySecretS = 2 }; 00092 00093 /// Available PIO states when verifying an ECDSA signature. 00094 enum GpioState { Unchanged, Conducting, HighImpedance }; 00095 00096 /// Holds a device memory page. 00097 typedef Core::array_span<uint_least8_t, 32> Page; 00098 00099 /// Challenge for an encrypted device memory page. 00100 typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge; 00101 00102 // Format page authentication input data. 00103 class PageAuthenticationData; 00104 00105 // Format authenticated write input data. 00106 class WriteAuthenticationData; 00107 00108 // Format compute secret input data. 00109 class ComputeSecretData; 00110 00111 // Format decryption HMAC input data. 00112 class DecryptionHmacData; 00113 00114 // Format encryption HMAC input data. 00115 class EncryptionHmacData; 00116 00117 // Access fields in the ROM Options page. 00118 class RomOptions; 00119 00120 // Access fields in the GPIO Control page. 00121 class GpioControl; 00122 00123 /// Page protection types. 00124 enum BlockProtectionType { 00125 RP = 0x01, ///< Read protection. 00126 WP = 0x02, ///< Write protection. 00127 EM = 0x04, ///< EPROM emulation mode. 00128 APH = 0x08, ///< Authentication Write Protection HMAC 00129 EPH = 0x10, ///< Encryption and Authentication Write Protection HMAC 00130 ECH = 0x40, ///< Encryption and write using shared key from ECDH 00131 ECW = 0x80 ///< Authentication Write Protection ECDSA 00132 }; 00133 typedef Core::FlagSet<BlockProtectionType, 8> BlockProtection; 00134 00135 explicit DS28C40(const Core::RunCommand & runCommand) 00136 : doRunCommand(runCommand) {} 00137 00138 void setRunCommand(const Core::RunCommand & runCommand) { 00139 doRunCommand = runCommand; 00140 } 00141 00142 /// @brief Write memory with no protection. 00143 /// @param pageNum Number of page to write. 00144 /// @param page Data to write. 00145 MaximInterfaceDevices_EXPORT Core::Result<void> 00146 writeMemory(int pageNum, Page::const_span page); 00147 00148 /// @brief Read memory with no protection. 00149 /// @param pageNum Number of page to read. 00150 /// @returns Data that was read. 00151 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00152 readMemory(int pageNum) const; 00153 00154 /// @brief Read memory with encryption. 00155 /// @param pageNum Number of page to read from. 00156 /// @param secret Secret to use for encryption. 00157 /// @returns Encryption challenge and encrypted page data that was read. 00158 MaximInterfaceDevices_EXPORT 00159 Core::Result<std::pair<EncryptionChallenge::array, Page::array> > 00160 encryptedReadMemory(int pageNum, KeySecret secret) const; 00161 00162 /// @brief Read the protection settings of a block. 00163 /// @param blockNum Number of block to read. 00164 /// @returns Secret/Key and protection set on the block. 00165 MaximInterfaceDevices_EXPORT 00166 Core::Result<std::pair<Core::Optional<KeySecret>, BlockProtection> > 00167 readBlockProtection(int blockNum) const; 00168 00169 /// @brief Set the protection settings of a block. 00170 /// @param blockNum Number of block to write. 00171 /// @param keySecret Secret/Key A or B. 00172 /// @param protection Protection to write. 00173 MaximInterfaceDevices_EXPORT Core::Result<void> 00174 setBlockProtection(int blockNum, KeySecret keySecret, 00175 const BlockProtection & protection); 00176 00177 /// @brief Compute and read page authentication with ECDSA. 00178 /// @param pageNum Number of page to authenticate. 00179 /// @param key 00180 /// Private key to use for authentication. 00181 /// Key S cannot be used with this command. 00182 /// @param challenge Random challenge used to prevent replay attacks. 00183 /// @returns Computed page signature. 00184 MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array> 00185 computeAndReadEcdsaPageAuthentication(int pageNum, KeySecret key, 00186 Page::const_span challenge) const; 00187 00188 /// @brief Compute and read page authentication with HMAC. 00189 /// @param pageNum Number of page to authenticate. 00190 /// @param secret 00191 /// Secret to use for authentication. 00192 /// Secret S cannot be used with this command. 00193 /// @param challenge Random challenge used to prevent replay attacks. 00194 /// @returns Computed page HMAC. 00195 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00196 computeAndReadSha256PageAuthentication(int pageNum, KeySecret secret, 00197 Page::const_span challenge) const; 00198 00199 /// @brief Compute a hash over multiple blocks. 00200 /// @param firstBlock True if this is the first block being hashed. 00201 /// @param lastBlock True if this is the last block being hashed. 00202 /// @param data 00203 /// Data block to hash. Should be 64 bytes unless this is the last block. 00204 MaximInterfaceDevices_EXPORT Core::Result<void> 00205 computeMultiblockHash(bool firstBlock, bool lastBlock, 00206 Core::span<const uint_least8_t> data); 00207 00208 /// @brief Verify ECDSA signature with data input. 00209 /// @param key Public key to use for verification. 00210 /// @param authorityKey Use the authority key instead of the standard key. 00211 /// @param gpioState New state of the GPIO pin if verification successful. 00212 /// @param signature Signature to verify. 00213 /// @param data Data to verify with length from 1 to 64. 00214 MaximInterfaceDevices_EXPORT Core::Result<void> 00215 verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, 00216 Core::Ecc256::Signature::const_span signature, 00217 Core::span<const uint_least8_t> data); 00218 00219 /// @brief Verify ECDSA signature with hash input. 00220 /// @param key Public key to use for verification. 00221 /// @param authorityKey Use the authority key instead of the standard key. 00222 /// @param gpioState New state of the GPIO pin if verification successful. 00223 /// @param signature Signature to verify. 00224 /// @param hash Hash of data to verify. 00225 MaximInterfaceDevices_EXPORT Core::Result<void> 00226 verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, 00227 Core::Ecc256::Signature::const_span signature, 00228 Page::const_span hash); 00229 00230 /// @brief 00231 /// Verify ECDSA signature with THASH input from Compute Multiblock Hash. 00232 /// @param key Public key to use for verification. 00233 /// @param authorityKey Use the authority key instead of the standard key. 00234 /// @param gpioState New state of the GPIO pin if verification successful. 00235 /// @param signature Signature to verify. 00236 MaximInterfaceDevices_EXPORT Core::Result<void> 00237 verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, 00238 Core::Ecc256::Signature::const_span signature); 00239 00240 /// @brief Authenticate a public key for authenticated writes. 00241 /// @param key 00242 /// Authority key to use for authentication. Key A or B can be selected. 00243 /// @param cert Certificate to use for authentication of Public Key S. 00244 /// @param certCustomization 00245 /// Certificate customization with length from 1 to 32. 00246 MaximInterfaceDevices_EXPORT Core::Result<void> 00247 authenticateEcdsaPublicKey(KeySecret key, 00248 Core::Ecc256::Signature::const_span cert, 00249 Core::span<const uint_least8_t> certCustomization); 00250 00251 /// @brief 00252 /// Authenticate a public key for ECDH and optionally authenticated writes. 00253 /// @param key 00254 /// Keys to use for authentication and ECDH key exchange. 00255 /// Key A or B can be selected. 00256 /// @param authWrites True to select authentication for writes. 00257 /// @param cert Certificate to use for authentication of Public Key S. 00258 /// @param certCustomization 00259 /// Certificate customization with length from 1 to 32. 00260 /// @param ecdhCustomization ECDH customization with length from 1 to 48. 00261 /// @note The maximum total customization length is 60 bytes. 00262 MaximInterfaceDevices_EXPORT Core::Result<void> 00263 authenticateEcdsaPublicKey(KeySecret key, bool authWrites, 00264 Core::Ecc256::Signature::const_span cert, 00265 Core::span<const uint_least8_t> certCustomization, 00266 Core::span<const uint_least8_t> ecdhCustomization); 00267 00268 /// @brief Write with ECDSA authentication. 00269 /// @param pageNum Number of page to write. 00270 /// @param useKeyS 00271 /// Use Public Key S instead of the authority key set in the block protection. 00272 /// @param newPageData Data to write. 00273 /// @param signature Signature to use for authentication of page data. 00274 MaximInterfaceDevices_EXPORT Core::Result<void> 00275 authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS, 00276 Page::const_span newPageData, 00277 Core::Ecc256::Signature::const_span signature); 00278 00279 /// @brief Write with ECDSA authentication and encryption. 00280 /// @param pageNum Number of page to write. 00281 /// @param useKeyS 00282 /// Use Public Key S instead of the authority key set in the block protection. 00283 /// @param newPageData Encrypted data to write. 00284 /// @param signature Signature to use for authentication of page data. 00285 /// @param challenge Challenge to use for decryption of page data. 00286 MaximInterfaceDevices_EXPORT Core::Result<void> 00287 authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS, 00288 Page::const_span newPageData, 00289 Core::Ecc256::Signature::const_span signature, 00290 EncryptionChallenge::const_span challenge); 00291 00292 /// @brief Write with SHA-256 HMAC authentication. 00293 /// @param pageNum Number of page to write. 00294 /// @param useSecretS 00295 /// Use Secret S instead of the secret set in the block protection. 00296 /// @param newPageData Data to write. 00297 /// @param hmac HMAC to use for authentication of page data. 00298 MaximInterfaceDevices_EXPORT Core::Result<void> 00299 authenticatedSha256WriteMemory(int pageNum, bool useSecretS, 00300 Page::const_span newPageData, 00301 Page::const_span hmac); 00302 00303 /// @brief Write with SHA-256 HMAC authentication and encryption. 00304 /// @param pageNum Number of page to write. 00305 /// @param useSecretS 00306 /// Use Secret S instead of the secret set in the block protection. 00307 /// @param newPageData Data to write. 00308 /// @param hmac HMAC to use for authentication of page data. 00309 /// @param challenge Challenge to use for decryption of page data. 00310 MaximInterfaceDevices_EXPORT Core::Result<void> 00311 authenticatedSha256WriteMemory(int pageNum, bool useSecretS, 00312 Page::const_span newPageData, 00313 Page::const_span hmac, 00314 EncryptionChallenge::const_span challenge); 00315 00316 /// @brief Compute a derivative SHA-256 secret from an existing secret. 00317 /// @param pageNum Number of page to use in computation. 00318 /// @param masterSecret Master secret to use in computation. 00319 /// @param destinationSecret 00320 /// Destination secret to receive the computation result. 00321 /// @param partialSecret Partial secret to use in computation. 00322 MaximInterfaceDevices_EXPORT Core::Result<void> 00323 computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret, 00324 KeySecret destinationSecret, 00325 Page::const_span partialSecret); 00326 00327 /// @brief Generate a new ECDSA key pair. 00328 /// @param key Key to generate. Key S cannot be used with this command. 00329 MaximInterfaceDevices_EXPORT Core::Result<void> 00330 generateEcc256KeyPair(KeySecret key); 00331 00332 /// @brief Read a block of random data from the RNG. 00333 /// @param[out] data Random data from RNG with length from 1 to 64. 00334 MaximInterfaceDevices_EXPORT Core::Result<void> 00335 readRng(Core::span<uint_least8_t> data) const; 00336 00337 /// Run entropy health test on the RNG. 00338 MaximInterfaceDevices_EXPORT Core::Result<void> entropyHealthTest() const; 00339 00340 MaximInterfaceDevices_EXPORT static const Core::error_category & 00341 errorCategory(); 00342 00343 private: 00344 enum HashType { HashInput, DataInput, THASH }; 00345 00346 Core::Result<void> 00347 verifyEcdsaSignature(KeySecret key, bool authorityKey, HashType hashType, 00348 GpioState gpioState, 00349 Core::Ecc256::Signature::const_span signature, 00350 Core::span<const uint_least8_t> buffer); 00351 00352 Core::Result<void> authenticateEcdsaPublicKey( 00353 KeySecret key, bool authWrites, Core::Ecc256::Signature::const_span cert, 00354 Core::span<const uint_least8_t> certCustomization, 00355 const Core::span<const uint_least8_t> * ecdhCustomization); 00356 00357 Core::Result<void> authenticatedEcdsaWriteMemory( 00358 int pageNum, bool useKeyS, Page::const_span newPageData, 00359 Core::Ecc256::Signature::const_span signature, 00360 const EncryptionChallenge::const_span * challenge); 00361 00362 Core::Result<void> authenticatedSha256WriteMemory( 00363 int pageNum, bool useSecretS, Page::const_span newPageData, 00364 Page::const_span hmac, const EncryptionChallenge::const_span * challenge); 00365 00366 Core::Result<Core::span<uint_least8_t> > 00367 runCommand(Core::span<const uint_least8_t> request, int delayTime, 00368 Core::span<uint_least8_t> response) const; 00369 00370 Core::Result<void> runCommand(Core::span<const uint_least8_t> request, 00371 int delayTime) const; 00372 00373 Core::RunCommand doRunCommand; 00374 }; 00375 00376 } // namespace MaximInterfaceDevices 00377 namespace MaximInterfaceCore { 00378 00379 template <> 00380 struct is_error_code_enum<MaximInterfaceDevices::DS28C40::ErrorValue> 00381 : true_type {}; 00382 00383 } // namespace MaximInterfaceCore 00384 namespace MaximInterfaceDevices { 00385 00386 inline Core::error_code make_error_code(DS28C40::ErrorValue e) { 00387 return Core::error_code(e, DS28C40::errorCategory()); 00388 } 00389 00390 /// @brief 00391 /// Hash arbitrary length data with successive Compute Multiblock Hash commands. 00392 /// @param device Device for computation. 00393 /// @param data Data to hash. 00394 MaximInterfaceDevices_EXPORT Core::Result<void> 00395 computeMultiblockHash(DS28C40 & device, Core::span<const uint_least8_t> data); 00396 00397 /// Format page authentication input data. 00398 class DS28C40::PageAuthenticationData { 00399 public: 00400 typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + 00401 1 + Core::ManId::size> 00402 Result; 00403 00404 PageAuthenticationData() : result_() {} 00405 00406 /// Formatted data result. 00407 Result::const_span result() const { return result_; } 00408 00409 /// @name ROM ID 00410 /// @brief 1-Wire ROM ID of the device. 00411 /// @{ 00412 00413 /// Get mutable ROM ID. 00414 Core::RomId::span romId() { 00415 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00416 } 00417 00418 /// Get immutable ROM ID. 00419 Core::RomId::const_span romId() const { 00420 return const_cast<PageAuthenticationData &>(*this).romId(); 00421 } 00422 00423 /// Set ROM ID. 00424 PageAuthenticationData & setRomId(Core::RomId::const_span romId) { 00425 copy(romId, this->romId()); 00426 return *this; 00427 } 00428 00429 /// Set ROM ID for use in anonymous mode. 00430 MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); 00431 00432 /// @} 00433 00434 /// @name Page 00435 /// @brief Data from a device memory page. 00436 /// @{ 00437 00438 /// Get mutable page. 00439 Page::span page() { 00440 return make_span(result_).subspan<pageIdx, Page::size>(); 00441 } 00442 00443 /// Get immutable page. 00444 Page::const_span page() const { 00445 return const_cast<PageAuthenticationData &>(*this).page(); 00446 } 00447 00448 /// Set page. 00449 PageAuthenticationData & setPage(Page::const_span page) { 00450 copy(page, this->page()); 00451 return *this; 00452 } 00453 00454 /// @} 00455 00456 /// @name Challenge 00457 /// @brief Random challenge used to prevent replay attacks. 00458 /// @{ 00459 00460 /// Get mutable Challenge. 00461 Page::span challenge() { 00462 return make_span(result_).subspan<challengeIdx, Page::size>(); 00463 } 00464 00465 /// Get immutable Challenge. 00466 Page::const_span challenge() const { 00467 return const_cast<PageAuthenticationData &>(*this).challenge(); 00468 } 00469 00470 /// Set Challenge. 00471 PageAuthenticationData & setChallenge(Page::const_span challenge) { 00472 copy(challenge, this->challenge()); 00473 return *this; 00474 } 00475 00476 /// @} 00477 00478 /// @name Page number 00479 /// @brief Number of the page to use data from. 00480 /// @{ 00481 00482 /// Get page number. 00483 int pageNum() const { return result_[pageNumIdx]; } 00484 00485 /// Set page number. 00486 PageAuthenticationData & setPageNum(int pageNum) { 00487 result_[pageNumIdx] = pageNum; 00488 return *this; 00489 } 00490 00491 /// @} 00492 00493 /// @name MAN ID 00494 /// @brief Manufacturer ID of the device. 00495 /// @{ 00496 00497 /// Get mutable MAN ID. 00498 Core::ManId::span manId() { 00499 return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); 00500 } 00501 00502 /// Get immutable MAN ID. 00503 Core::ManId::const_span manId() const { 00504 return const_cast<PageAuthenticationData &>(*this).manId(); 00505 } 00506 00507 /// Set MAN ID. 00508 PageAuthenticationData & setManId(Core::ManId::const_span manId) { 00509 copy(manId, this->manId()); 00510 return *this; 00511 } 00512 00513 /// @} 00514 00515 private: 00516 static const size_t romIdIdx = 0; 00517 static const size_t pageIdx = romIdIdx + Core::RomId::size; 00518 static const size_t challengeIdx = pageIdx + Page::size; 00519 static const size_t pageNumIdx = challengeIdx + Page::size; 00520 static const size_t manIdIdx = pageNumIdx + 1; 00521 00522 Result::array result_; 00523 }; 00524 00525 /// Format authenticated write input data. 00526 class DS28C40::WriteAuthenticationData { 00527 public: 00528 typedef PageAuthenticationData::Result Result; 00529 00530 WriteAuthenticationData() : data() { setPageNum(0); } 00531 00532 /// Formatted data result. 00533 Result::const_span result() const { return data.result(); } 00534 00535 /// @name ROM ID 00536 /// @brief 1-Wire ROM ID of the device. 00537 /// @{ 00538 00539 /// Get mutable ROM ID. 00540 Core::RomId::span romId() { return data.romId(); } 00541 00542 /// Get immutable ROM ID. 00543 Core::RomId::const_span romId() const { return data.romId(); } 00544 00545 /// Set ROM ID. 00546 WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { 00547 data.setRomId(romId); 00548 return *this; 00549 } 00550 00551 /// Set ROM ID for use in anonymous mode. 00552 WriteAuthenticationData & setAnonymousRomId() { 00553 data.setAnonymousRomId(); 00554 return *this; 00555 } 00556 00557 /// @} 00558 00559 /// @name Old page 00560 /// @brief Existing data contained in the page. 00561 /// @{ 00562 00563 /// Get mutable old page. 00564 Page::span oldPage() { return data.page(); } 00565 00566 /// Get immutable old page. 00567 Page::const_span oldPage() const { return data.page(); } 00568 00569 /// Set old page. 00570 WriteAuthenticationData & setOldPage(Page::const_span oldPage) { 00571 data.setPage(oldPage); 00572 return *this; 00573 } 00574 00575 /// @} 00576 00577 /// @name New page 00578 /// @brief New data to write to the page. 00579 /// @{ 00580 00581 /// Get mutable new page. 00582 Page::span newPage() { return data.challenge(); } 00583 00584 /// Get immutable new page. 00585 Page::const_span newPage() const { return data.challenge(); } 00586 00587 /// Set new page. 00588 WriteAuthenticationData & setNewPage(Page::const_span newPage) { 00589 data.setChallenge(newPage); 00590 return *this; 00591 } 00592 00593 /// @} 00594 00595 /// @name Page number 00596 /// @brief Page number for write operation. 00597 /// @{ 00598 00599 /// Get page number. 00600 int pageNum() const { return data.pageNum() & 0x7F; } 00601 00602 /// Set page number. 00603 WriteAuthenticationData & setPageNum(int pageNum) { 00604 data.setPageNum(pageNum | 0x80); 00605 return *this; 00606 } 00607 00608 /// @} 00609 00610 /// @name MAN ID 00611 /// @brief Manufacturer ID of the device. 00612 /// @{ 00613 00614 /// Get mutable MAN ID. 00615 Core::ManId::span manId() { return data.manId(); } 00616 00617 /// Get immutable MAN ID. 00618 Core::ManId::const_span manId() const { return data.manId(); } 00619 00620 /// Set MAN ID. 00621 WriteAuthenticationData & setManId(Core::ManId::const_span manId) { 00622 data.setManId(manId); 00623 return *this; 00624 } 00625 00626 /// @} 00627 00628 private: 00629 PageAuthenticationData data; 00630 }; 00631 00632 /// Format compute secret input data. 00633 class DS28C40::ComputeSecretData { 00634 public: 00635 typedef PageAuthenticationData::Result Result; 00636 00637 MaximInterfaceDevices_EXPORT ComputeSecretData(); 00638 00639 /// Formatted data result. 00640 Result::const_span result() const { return data.result(); } 00641 00642 /// @name ROM ID 00643 /// @brief 1-Wire ROM ID of the device. 00644 /// @{ 00645 00646 /// Get mutable ROM ID. 00647 Core::RomId::span romId() { return data.romId(); } 00648 00649 /// Get immutable ROM ID. 00650 Core::RomId::const_span romId() const { return data.romId(); } 00651 00652 /// Set ROM ID. 00653 ComputeSecretData & setRomId(Core::RomId::const_span romId) { 00654 data.setRomId(romId); 00655 return *this; 00656 } 00657 00658 /// @} 00659 00660 /// @name Binding Data 00661 /// @brief Binding Data contained in the selected page. 00662 /// @{ 00663 00664 /// Get mutable Binding Data. 00665 Page::span bindingData() { return data.page(); } 00666 00667 /// Get immutable Binding Data. 00668 Page::const_span bindingData() const { return data.page(); } 00669 00670 /// Set Binding Data. 00671 ComputeSecretData & setBindingData(Page::const_span bindingData) { 00672 data.setPage(bindingData); 00673 return *this; 00674 } 00675 00676 /// @} 00677 00678 /// @name Partial Secret 00679 /// @brief Partial Secret used for customization. 00680 /// @{ 00681 00682 /// Get mutable Partial Secret. 00683 Page::span partialSecret() { return data.challenge(); } 00684 00685 /// Get immutable Partial Secret. 00686 Page::const_span partialSecret() const { return data.challenge(); } 00687 00688 /// Set Partial Secret. 00689 ComputeSecretData & setPartialSecret(Page::const_span partialSecret) { 00690 data.setChallenge(partialSecret); 00691 return *this; 00692 } 00693 00694 /// @} 00695 00696 /// @name Page number 00697 /// @brief Page number for Binding Data. 00698 /// @{ 00699 00700 /// Get page number. 00701 int pageNum() const { return data.pageNum() & 0x3F; } 00702 00703 /// Set page number. 00704 ComputeSecretData & setPageNum(int pageNum) { 00705 data.setPageNum(pageNum | 0xC0); 00706 return *this; 00707 } 00708 00709 /// @} 00710 00711 /// @name MAN ID 00712 /// @brief Manufacturer ID of the device. 00713 /// @{ 00714 00715 /// Get immutable MAN ID. 00716 Core::ManId::const_span manId() const { return data.manId(); } 00717 00718 /// Set MAN ID. 00719 MaximInterfaceDevices_EXPORT ComputeSecretData & 00720 setManId(Core::ManId::const_span manId); 00721 00722 /// @} 00723 00724 private: 00725 PageAuthenticationData data; 00726 }; 00727 00728 /// Format decryption HMAC input data. 00729 class DS28C40::DecryptionHmacData { 00730 public: 00731 typedef Core::array_span<uint_least8_t, EncryptionChallenge::size + 00732 Core::RomId::size + 1 + 00733 Core::ManId::size> 00734 Result; 00735 00736 DecryptionHmacData() : result_() {} 00737 00738 /// Formatted data result. 00739 Result::const_span result() const { return result_; } 00740 00741 /// @name Encryption Challenge 00742 /// @brief Random challenge used to prevent replay attacks. 00743 /// @{ 00744 00745 /// Get mutable Encryption Challenge. 00746 EncryptionChallenge::span encryptionChallenge() { 00747 return make_span(result_) 00748 .subspan<encryptionChallengeIdx, EncryptionChallenge::size>(); 00749 } 00750 00751 /// Get immutable Encryption Challenge. 00752 EncryptionChallenge::const_span encryptionChallenge() const { 00753 return const_cast<DecryptionHmacData &>(*this).encryptionChallenge(); 00754 } 00755 00756 /// Set Encryption Challenge. 00757 DecryptionHmacData & 00758 setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { 00759 copy(encryptionChallenge, this->encryptionChallenge()); 00760 return *this; 00761 } 00762 00763 /// @} 00764 00765 /// @name ROM ID 00766 /// @brief 1-Wire ROM ID of the device. 00767 /// @{ 00768 00769 /// Get mutable ROM ID. 00770 Core::RomId::span romId() { 00771 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00772 } 00773 00774 /// Get immutable ROM ID. 00775 Core::RomId::const_span romId() const { 00776 return const_cast<DecryptionHmacData &>(*this).romId(); 00777 } 00778 00779 /// Set ROM ID. 00780 DecryptionHmacData & setRomId(Core::RomId::const_span romId) { 00781 copy(romId, this->romId()); 00782 return *this; 00783 } 00784 00785 /// Set ROM ID for use in anonymous mode. 00786 MaximInterfaceDevices_EXPORT DecryptionHmacData & setAnonymousRomId(); 00787 00788 /// @} 00789 00790 /// @name Page number 00791 /// @brief Number of the page to use data from. 00792 /// @{ 00793 00794 /// Get page number. 00795 int pageNum() const { return result_[pageNumIdx]; } 00796 00797 /// Set page number. 00798 DecryptionHmacData & setPageNum(int pageNum) { 00799 result_[pageNumIdx] = pageNum; 00800 return *this; 00801 } 00802 00803 /// @} 00804 00805 /// @name MAN ID 00806 /// @brief Manufacturer ID of the device. 00807 /// @{ 00808 00809 /// Get mutable MAN ID. 00810 Core::ManId::span manId() { 00811 return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); 00812 } 00813 00814 /// Get immutable MAN ID. 00815 Core::ManId::const_span manId() const { 00816 return const_cast<DecryptionHmacData &>(*this).manId(); 00817 } 00818 00819 /// Set MAN ID. 00820 DecryptionHmacData & setManId(Core::ManId::const_span manId) { 00821 copy(manId, this->manId()); 00822 return *this; 00823 } 00824 00825 /// @} 00826 00827 private: 00828 static const size_t encryptionChallengeIdx = 0; 00829 static const size_t romIdIdx = 00830 encryptionChallengeIdx + EncryptionChallenge::size; 00831 static const size_t pageNumIdx = romIdIdx + Core::RomId::size; 00832 static const size_t manIdIdx = pageNumIdx + 1; 00833 00834 Result::array result_; 00835 }; 00836 00837 /// Format encryption HMAC input data. 00838 class DS28C40::EncryptionHmacData { 00839 public: 00840 typedef DecryptionHmacData::Result Result; 00841 00842 EncryptionHmacData() : data() { setPageNum(0); } 00843 00844 /// Formatted data result. 00845 Result::const_span result() const { return data.result(); } 00846 00847 /// @name Encryption Challenge 00848 /// @brief Random challenge used to prevent replay attacks. 00849 /// @{ 00850 00851 /// Get mutable Encryption Challenge. 00852 EncryptionChallenge::span encryptionChallenge() { 00853 return data.encryptionChallenge(); 00854 } 00855 00856 /// Get immutable Encryption Challenge. 00857 EncryptionChallenge::const_span encryptionChallenge() const { 00858 return data.encryptionChallenge(); 00859 } 00860 00861 /// Set Encryption Challenge. 00862 EncryptionHmacData & 00863 setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { 00864 data.setEncryptionChallenge(encryptionChallenge); 00865 return *this; 00866 } 00867 00868 /// @} 00869 00870 /// @name ROM ID 00871 /// @brief 1-Wire ROM ID of the device. 00872 /// @{ 00873 00874 /// Get mutable ROM ID. 00875 Core::RomId::span romId() { return data.romId(); } 00876 00877 /// Get immutable ROM ID. 00878 Core::RomId::const_span romId() const { return data.romId(); } 00879 00880 /// Set ROM ID. 00881 EncryptionHmacData & setRomId(Core::RomId::const_span romId) { 00882 data.setRomId(romId); 00883 return *this; 00884 } 00885 00886 /// Set ROM ID for use in anonymous mode. 00887 EncryptionHmacData & setAnonymousRomId() { 00888 data.setAnonymousRomId(); 00889 return *this; 00890 } 00891 00892 /// @} 00893 00894 /// @name Page number 00895 /// @brief Number of the page to use data from. 00896 /// @{ 00897 00898 /// Get page number. 00899 int pageNum() const { return data.pageNum() & 0x7F; } 00900 00901 /// Set page number. 00902 EncryptionHmacData & setPageNum(int pageNum) { 00903 data.setPageNum(pageNum | 0x80); 00904 return *this; 00905 } 00906 00907 /// @} 00908 00909 /// @name MAN ID 00910 /// @brief Manufacturer ID of the device. 00911 /// @{ 00912 00913 /// Get mutable MAN ID. 00914 Core::ManId::span manId() { return data.manId(); } 00915 00916 /// Get immutable MAN ID. 00917 Core::ManId::const_span manId() const { return data.manId(); } 00918 00919 /// Set MAN ID. 00920 EncryptionHmacData & setManId(Core::ManId::const_span manId) { 00921 data.setManId(manId); 00922 return *this; 00923 } 00924 00925 /// @} 00926 00927 private: 00928 DecryptionHmacData data; 00929 }; 00930 00931 /// Access fields in the ROM Options page. 00932 class DS28C40::RomOptions { 00933 public: 00934 explicit RomOptions(Page::span page) : page(page) {} 00935 00936 bool anonymous() const { return page[anonymousIdx] == anonymousValue; } 00937 00938 void setAnonymous(bool anonymous) { 00939 page[anonymousIdx] = (anonymous ? anonymousValue : 0); 00940 } 00941 00942 Core::ManId::const_span manId() const { 00943 return page.subspan<22, Core::ManId::size>(); 00944 } 00945 00946 Core::RomId::const_span romId() const { 00947 return page.subspan<24, Core::RomId::size>(); 00948 } 00949 00950 private: 00951 static const Page::span::index_type anonymousIdx = 1; 00952 static const Page::span::value_type anonymousValue = 0xAA; 00953 00954 Page::span page; 00955 }; 00956 00957 /// Access fields in the GPIO Control page. 00958 class DS28C40::GpioControl { 00959 public: 00960 explicit GpioControl(Page::span page) : page(page) {} 00961 00962 bool conducting() const { return page[conductingIdx] == conductingValue; } 00963 00964 void setConducting(bool conducting) { 00965 page[conductingIdx] = (conducting ? conductingValue : 0x55); 00966 } 00967 00968 bool level() const { return page[2] == 0x55; } 00969 00970 private: 00971 static const Page::span::index_type conductingIdx = 0; 00972 static const Page::span::value_type conductingValue = 0xAA; 00973 00974 Page::span page; 00975 }; 00976 00977 } // namespace MaximInterfaceDevices 00978 00979 #endif
Generated on Tue Jul 12 2022 11:13:10 by
1.7.2