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