Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28C36_DS2476.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_DS28C36_DS2476_hpp 00034 #define MaximInterfaceDevices_DS28C36_DS2476_hpp 00035 00036 #include <stdint.h> 00037 #include <utility> 00038 #include <vector> 00039 #include <MaximInterfaceCore/Algorithm.hpp> 00040 #include <MaximInterfaceCore/array_span.hpp> 00041 #include <MaximInterfaceCore/Ecc256.hpp> 00042 #include <MaximInterfaceCore/FlagSet.hpp> 00043 #include <MaximInterfaceCore/I2CMaster.hpp> 00044 #include <MaximInterfaceCore/ManId.hpp> 00045 #include <MaximInterfaceCore/RomId.hpp> 00046 #include <MaximInterfaceCore/Sleep.hpp> 00047 #include <MaximInterfaceCore/system_error.hpp> 00048 #include "Config.hpp" 00049 00050 namespace MaximInterfaceDevices { 00051 00052 /// Interface to the DS28C36 authenticator. 00053 class DS28C36 { 00054 public: 00055 /// Device command results. 00056 enum ErrorValue { 00057 ProtectionError = 0x55, 00058 InvalidParameterError = 0x77, 00059 InvalidSequenceError = 0x33, 00060 InvalidEcdsaInputOrResultError = 0x22, 00061 AuthenticationError = 0x100, 00062 InvalidResponseError = 0x101 ///< Response does not match expected format. 00063 }; 00064 00065 /// @name Device memory pages 00066 /// @{ 00067 00068 static const int publicKeyAxPage = 16; 00069 static const int publicKeyAyPage = 17; 00070 static const int publicKeyBxPage = 18; 00071 static const int publicKeyByPage = 19; 00072 static const int publicKeyCxPage = 20; 00073 static const int publicKeyCyPage = 21; 00074 static const int privateKeyAPage = 22; 00075 static const int privateKeyBPage = 23; 00076 static const int privateKeyCPage = 24; 00077 static const int secretAPage = 25; 00078 static const int secretBPage = 26; 00079 static const int decrementCounterPage = 27; 00080 static const int romOptionsPage = 28; 00081 static const int gpioControlPage = 29; 00082 static const int publicKeySxPage = 30; 00083 static const int publicKeySyPage = 31; 00084 00085 /// @} 00086 00087 /// Number of memory pages on the device. 00088 static const int memoryPages = 32; 00089 00090 /// Available keys for ECDSA operations. 00091 enum KeyNum { KeyNumA = 0, KeyNumB = 1, KeyNumC = 2, KeyNumS = 3 }; 00092 00093 /// Available secrets for HMAC operations. 00094 enum SecretNum { SecretNumA = 0, SecretNumB = 1, SecretNumS = 2 }; 00095 00096 /// Data hash type when verifying an ECDSA signature. 00097 enum HashType { 00098 HashInBuffer = 0, ///< Hash is loaded in the buffer. 00099 DataInBuffer = 1, ///< Compute hash from data loaded in the buffer. 00100 THASH = 2 ///< Use THASH from Compute Multiblock Hash command. 00101 }; 00102 00103 /// Available PIO states when verifying an ECDSA signature. 00104 enum PioState { Unchanged, Conducting, HighImpedance }; 00105 00106 /// Holds a device memory page. 00107 typedef Core::array_span<uint_least8_t, 32> Page; 00108 00109 // Format page authentication input data. 00110 class PageAuthenticationData; 00111 00112 // Format authenticated write input data. 00113 class WriteAuthenticationData; 00114 00115 // Format compute secret input data. 00116 class ComputeSecretData; 00117 00118 // Format encryption or decryption HMAC input data. 00119 class EncryptionHmacData; 00120 00121 // Access fields in the ROM Options page. 00122 class RomOptions; 00123 00124 // Access fields in the GPIO Control page. 00125 class GpioControl; 00126 00127 /// Page protection types. 00128 enum PageProtectionType { 00129 RP = 0x01, ///< Read protection. 00130 WP = 0x02, ///< Write protection. 00131 EM = 0x04, ///< EPROM emulation mode. 00132 APH = 0x08, ///< Authentication write protection HMAC. 00133 EPH = 0x10, ///< Encryption and authenticated write protection HMAC. 00134 AUTH = 0x20, ///< Public Key C is set to authority public key. 00135 ECH = 0x40, ///< Encrypted read and write using shared key from ECDH. 00136 ECW = 0x80 ///< Authentication write protection ECDSA. 00137 }; 00138 typedef Core::FlagSet<PageProtectionType, 8> PageProtection; 00139 00140 /// Challenge for an encrypted device memory page. 00141 typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge; 00142 00143 DS28C36(Core::Sleep & sleep, Core::I2CMaster & master, 00144 uint_least8_t address = 0x36) 00145 : sleep_(&sleep), master(&master), address_(address & 0xFE) {} 00146 00147 void setSleep(Core::Sleep & sleep) { sleep_ = &sleep; } 00148 00149 void setMaster(Core::I2CMaster & master) { this->master = &master; } 00150 00151 uint_least8_t address() const { return address_; } 00152 00153 void setAddress(uint_least8_t address) { address_ = address & 0xFE; } 00154 00155 /// @brief Write memory with no protection. 00156 /// @param pageNum Number of page to write. 00157 /// @param page Data to write. 00158 MaximInterfaceDevices_EXPORT Core::Result<void> 00159 writeMemory(int pageNum, Page::const_span page); 00160 00161 /// @brief Read memory with no protection. 00162 /// @param pageNum Number of page to read. 00163 /// @returns Data that was read. 00164 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00165 readMemory(int pageNum) const; 00166 00167 /// @brief Write the temporary buffer. 00168 /// @param data Data to write. 00169 MaximInterfaceDevices_EXPORT Core::Result<void> 00170 writeBuffer(Core::span<const uint_least8_t> data); 00171 00172 /// @brief Read the temporary buffer. 00173 /// @returns Data that was read. 00174 MaximInterfaceDevices_EXPORT Core::Result<std::vector<uint_least8_t> > 00175 readBuffer() const; 00176 00177 /// @brief Read the protection settings of a page. 00178 /// @param pageNum Number of page to read. 00179 /// @returns Protection that was read. 00180 MaximInterfaceDevices_EXPORT Core::Result<PageProtection> 00181 readPageProtection(int pageNum) const; 00182 00183 /// @brief Set the protection settings of a page. 00184 /// @param pageNum Number of page to write. 00185 /// @param protection Protection to write. 00186 MaximInterfaceDevices_EXPORT Core::Result<void> 00187 setPageProtection(int pageNum, const PageProtection & protection); 00188 00189 /// Decrement the decrement-only counter. 00190 MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter(); 00191 00192 /// @brief Read a block of random data from the RNG. 00193 /// @param[out] data Random data from RNG with length from 1 to 64. 00194 MaximInterfaceDevices_EXPORT Core::Result<void> 00195 readRng(Core::span<uint_least8_t> data) const; 00196 00197 /// @brief Read memory with encryption. 00198 /// @param pageNum Number of page to read from. 00199 /// @param secretNum Secret to use for encryption. 00200 /// @returns Encryption challenge and encrypted page data that was read. 00201 MaximInterfaceDevices_EXPORT 00202 Core::Result<std::pair<EncryptionChallenge::array, Page::array> > 00203 encryptedReadMemory(int pageNum, SecretNum secretNum) const; 00204 00205 /// @brief Compute and read page authentication with ECDSA. 00206 /// @param pageNum Number of page to authenticate. 00207 /// @param keyNum 00208 /// Private key to use for authentication. 00209 /// Key S cannot be used with this command. 00210 /// @returns Computed page signature. 00211 MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array> 00212 computeAndReadPageAuthentication(int pageNum, KeyNum keyNum) const; 00213 00214 /// @brief Compute and read page authentication with HMAC. 00215 /// @param pageNum Number of page to authenticate. 00216 /// @param secretNum Secret to use for authentication. 00217 /// @returns Computed page HMAC. 00218 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00219 computeAndReadPageAuthentication(int pageNum, SecretNum secretNum) const; 00220 00221 /// @brief Write with SHA2 authentication. 00222 /// @param pageNum Number of page to write. 00223 /// @param secretNum Secret to use for authentication. 00224 /// @param page Data to write. 00225 MaximInterfaceDevices_EXPORT Core::Result<void> 00226 authenticatedSha2WriteMemory(int pageNum, SecretNum secretNum, 00227 Page::const_span page); 00228 00229 /// @brief Compute SHA2 secret and optionally lock. 00230 /// @param pageNum Number of page to use in computation. 00231 /// @param msecretNum Master secret to use in computation. 00232 /// @param dsecretNum Destination secret to receive the computation result. 00233 /// @param writeProtectEnable 00234 /// True to lock the destination secret against further writes. 00235 MaximInterfaceDevices_EXPORT Core::Result<void> 00236 computeAndLockSha2Secret(int pageNum, SecretNum msecretNum, 00237 SecretNum dsecretNum, bool writeProtectEnable); 00238 00239 /// @brief Generate a new ECDSA key pair. 00240 /// @param keyNum Key to generate. Key S cannot be used with this command. 00241 /// @param writeProtectEnable True to lock the key against further writes. 00242 MaximInterfaceDevices_EXPORT Core::Result<void> 00243 generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable); 00244 00245 /// @brief Compute a hash over multiple blocks. 00246 /// @param firstBlock True if this is the first block being hashed. 00247 /// @param lastBlock True if this is the last block being hashed. 00248 /// @param data 00249 /// Data block to hash. Should be 64 bytes unless this is the last block. 00250 MaximInterfaceDevices_EXPORT Core::Result<void> 00251 computeMultiblockHash(bool firstBlock, bool lastBlock, 00252 Core::span<const uint_least8_t> data); 00253 00254 /// @brief Verify ECDSA signature. 00255 /// @param keyNum Public key to use for verification. 00256 /// @param hashType Source of the data hash input. 00257 /// @param signature Signature to verify. 00258 /// @param pioa New state of PIOA if verification successful. 00259 /// @param piob New state of PIOB if verification successful. 00260 MaximInterfaceDevices_EXPORT Core::Result<void> 00261 verifyEcdsaSignature(KeyNum keyNum, HashType hashType, 00262 Core::Ecc256::Signature::const_span signature, 00263 PioState pioa = Unchanged, PioState piob = Unchanged); 00264 00265 /// @brief 00266 /// Authenticate a public key for authenticated writes or encrypted reads 00267 /// with ECDH. 00268 /// @param authWrites True to select authentication for writes. 00269 /// @param ecdh True to select ECDH key exchange. 00270 /// @param keyNum 00271 /// Private key to use for ECDH key exchange. Key A or B can be selected. 00272 /// @param csOffset Certificate customization field ending offset in buffer. 00273 /// @param signature Signature to use for authentication of public key S. 00274 MaximInterfaceDevices_EXPORT Core::Result<void> 00275 authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum, 00276 int csOffset, 00277 Core::Ecc256::Signature::const_span signature); 00278 00279 /// @brief Write with ECDSA authentication. 00280 /// @param pageNum Number of page to write. 00281 /// @param page Data to write. 00282 MaximInterfaceDevices_EXPORT Core::Result<void> 00283 authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page); 00284 00285 MaximInterfaceDevices_EXPORT static const Core::error_category & 00286 errorCategory(); 00287 00288 protected: 00289 // Timing constants. 00290 static const int generateEcdsaSignatureTimeMs = 50; 00291 static const int generateEccKeyPairTimeMs = 100; 00292 static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150; 00293 static const int sha256ComputationTimeMs = 3; 00294 static const int readMemoryTimeMs = /*1*/ 2; 00295 static const int writeMemoryTimeMs = 15; 00296 00297 Core::Result<void> 00298 writeCommand(uint_least8_t command, 00299 Core::span<const uint_least8_t> parameters) const; 00300 00301 Core::Result<void> writeCommand(uint_least8_t command) const { 00302 return writeCommand(command, Core::span<const uint_least8_t>()); 00303 } 00304 00305 Core::Result<Core::span<uint_least8_t>::index_type> 00306 readVariableLengthResponse(Core::span<uint_least8_t> response) const; 00307 00308 Core::Result<void> 00309 readFixedLengthResponse(Core::span<uint_least8_t> response) const; 00310 00311 void sleep(int ms) const { sleep_->invoke(ms); } 00312 00313 private: 00314 enum AuthType { 00315 HmacWithSecretA = 0, 00316 HmacWithSecretB = 1, 00317 HmacWithSecretS = 2, 00318 EcdsaWithKeyA = 3, 00319 EcdsaWithKeyB = 4, 00320 EcdsaWithKeyC = 5 00321 }; 00322 00323 Core::Result<void> computeAndReadPageAuthentication(int pageNum, 00324 AuthType authType) const; 00325 00326 const Core::Sleep * sleep_; 00327 Core::I2CMaster * master; 00328 uint_least8_t address_; 00329 }; 00330 00331 /// Interface to the DS2476 coprocessor. 00332 class DS2476 : public DS28C36 { 00333 public: 00334 DS2476(Core::Sleep & sleep, Core::I2CMaster & master, 00335 uint_least8_t address = 0x76) 00336 : DS28C36(sleep, master, address) {} 00337 00338 /// @brief Generate ECDSA signature. 00339 /// @param keyNum 00340 /// Private key to use to create signature. 00341 /// Key S cannot be used with this command. 00342 /// @returns Computed signature. 00343 MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array> 00344 generateEcdsaSignature(KeyNum keyNum) const; 00345 00346 /// @brief Compute unique SHA2 secret. 00347 /// @param msecretNum Master secret to use in computation. 00348 MaximInterfaceDevices_EXPORT Core::Result<void> 00349 computeSha2UniqueSecret(SecretNum msecretNum); 00350 00351 /// @brief Compute SHA2 HMAC. 00352 /// @returns Computed HMAC. 00353 MaximInterfaceDevices_EXPORT Core::Result<Page::array> 00354 computeSha2Hmac() const; 00355 }; 00356 00357 } // namespace MaximInterfaceDevices 00358 namespace MaximInterfaceCore { 00359 00360 template <> 00361 struct is_error_code_enum<MaximInterfaceDevices::DS28C36::ErrorValue> 00362 : true_type {}; 00363 00364 } // namespace MaximInterfaceCore 00365 namespace MaximInterfaceDevices { 00366 00367 inline Core::error_code make_error_code(DS28C36::ErrorValue e) { 00368 return Core::error_code(e, DS28C36::errorCategory()); 00369 } 00370 00371 /// @brief 00372 /// Hash arbitrary length data with successive Compute Multiblock Hash commands. 00373 /// @param ds28c36 Device for computation. 00374 /// @param data Data to hash. 00375 MaximInterfaceDevices_EXPORT Core::Result<void> 00376 computeMultiblockHash(DS28C36 & ds28c36, Core::span<const uint_least8_t> data); 00377 00378 /// @brief Verify ECDSA signature. 00379 /// @param ds28c36 Device for computation. 00380 /// @param publicKey Public key to use for verification. 00381 /// @param data Data to verify. 00382 /// @param signature Signature to verify. 00383 /// @param pioa New state of PIOA if verification successful. 00384 /// @param piob New state of PIOB if verification successful. 00385 MaximInterfaceDevices_EXPORT Core::Result<void> 00386 verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey, 00387 Core::span<const uint_least8_t> data, 00388 Core::Ecc256::Signature::const_span signature, 00389 DS28C36::PioState pioa = DS28C36::Unchanged, 00390 DS28C36::PioState piob = DS28C36::Unchanged); 00391 00392 /// @brief Verify ECDSA signature. 00393 /// @param ds28c36 Device for computation. 00394 /// @param publicKey 00395 /// Public key to use for verification which is loaded into Public Key S. 00396 /// @param data Data to verify. 00397 /// @param signature Signature to verify. 00398 /// @param pioa New state of PIOA if verification successful. 00399 /// @param piob New state of PIOB if verification successful. 00400 MaximInterfaceDevices_EXPORT Core::Result<void> 00401 verifyEcdsaSignature(DS28C36 & ds28c36, 00402 Core::Ecc256::PublicKey::const_span publicKey, 00403 Core::span<const uint_least8_t> data, 00404 Core::Ecc256::Signature::const_span signature, 00405 DS28C36::PioState pioa = DS28C36::Unchanged, 00406 DS28C36::PioState piob = DS28C36::Unchanged); 00407 00408 /// @brief 00409 /// Enable coprocessor functionality on the DS2476 by writing to the 00410 /// GPIO Control page. 00411 MaximInterfaceDevices_EXPORT Core::Result<void> 00412 enableCoprocessor(DS2476 & ds2476); 00413 00414 /// @brief 00415 /// Disable blocking of the ROM ID on the DS2476 by writing to the 00416 /// ROM Options page. 00417 MaximInterfaceDevices_EXPORT Core::Result<void> enableRomId(DS2476 & ds2476); 00418 00419 /// Format page authentication input data. 00420 class DS28C36::PageAuthenticationData { 00421 public: 00422 typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + 00423 1 + Core::ManId::size> 00424 Result; 00425 00426 PageAuthenticationData() : result_() {} 00427 00428 /// Formatted data result. 00429 Result::const_span result() const { return result_; } 00430 00431 /// @name ROM ID 00432 /// @brief 1-Wire ROM ID of the device. 00433 /// @{ 00434 00435 /// Get mutable ROM ID. 00436 Core::RomId::span romId() { 00437 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00438 } 00439 00440 /// Get immutable ROM ID. 00441 Core::RomId::const_span romId() const { 00442 return const_cast<PageAuthenticationData &>(*this).romId(); 00443 } 00444 00445 /// Set ROM ID. 00446 PageAuthenticationData & setRomId(Core::RomId::const_span romId) { 00447 copy(romId, this->romId()); 00448 return *this; 00449 } 00450 00451 /// Set ROM ID for use in anonymous mode. 00452 MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); 00453 00454 /// @} 00455 00456 /// @name Page 00457 /// @brief Data from a device memory page. 00458 /// @{ 00459 00460 /// Get mutable page. 00461 Page::span page() { 00462 return make_span(result_).subspan<pageIdx, Page::size>(); 00463 } 00464 00465 /// Get immutable page. 00466 Page::const_span page() const { 00467 return const_cast<PageAuthenticationData &>(*this).page(); 00468 } 00469 00470 /// Set page. 00471 PageAuthenticationData & setPage(Page::const_span page) { 00472 copy(page, this->page()); 00473 return *this; 00474 } 00475 00476 /// @} 00477 00478 /// @name Challenge 00479 /// @brief Random challenge used to prevent replay attacks. 00480 /// @{ 00481 00482 /// Get mutable Challenge. 00483 Page::span challenge() { 00484 return make_span(result_).subspan<challengeIdx, Page::size>(); 00485 } 00486 00487 /// Get immutable Challenge. 00488 Page::const_span challenge() const { 00489 return const_cast<PageAuthenticationData &>(*this).challenge(); 00490 } 00491 00492 /// Set Challenge. 00493 PageAuthenticationData & setChallenge(Page::const_span challenge) { 00494 copy(challenge, this->challenge()); 00495 return *this; 00496 } 00497 00498 /// @} 00499 00500 /// @name Page number 00501 /// @brief Number of the page to use data from. 00502 /// @{ 00503 00504 /// Get page number. 00505 int pageNum() const { return result_[pageNumIdx]; } 00506 00507 /// Set page number. 00508 PageAuthenticationData & setPageNum(int pageNum) { 00509 result_[pageNumIdx] = pageNum; 00510 return *this; 00511 } 00512 00513 /// @} 00514 00515 /// @name MAN ID 00516 /// @brief Manufacturer ID of the device. 00517 /// @{ 00518 00519 /// Get mutable MAN ID. 00520 Core::ManId::span manId() { 00521 return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); 00522 } 00523 00524 /// Get immutable MAN ID. 00525 Core::ManId::const_span manId() const { 00526 return const_cast<PageAuthenticationData &>(*this).manId(); 00527 } 00528 00529 /// Set MAN ID. 00530 PageAuthenticationData & setManId(Core::ManId::const_span manId) { 00531 copy(manId, this->manId()); 00532 return *this; 00533 } 00534 00535 /// @} 00536 00537 private: 00538 static const size_t romIdIdx = 0; 00539 static const size_t pageIdx = romIdIdx + Core::RomId::size; 00540 static const size_t challengeIdx = pageIdx + Page::size; 00541 static const size_t pageNumIdx = challengeIdx + Page::size; 00542 static const size_t manIdIdx = pageNumIdx + 1; 00543 00544 Result::array result_; 00545 }; 00546 00547 /// Format authenticated write input data. 00548 class DS28C36::WriteAuthenticationData { 00549 public: 00550 typedef PageAuthenticationData::Result Result; 00551 00552 WriteAuthenticationData() : data() {} 00553 00554 /// Formatted data result. 00555 Result::const_span result() const { return data.result(); } 00556 00557 /// @name ROM ID 00558 /// @brief 1-Wire ROM ID of the device. 00559 /// @{ 00560 00561 /// Get mutable ROM ID. 00562 Core::RomId::span romId() { return data.romId(); } 00563 00564 /// Get immutable ROM ID. 00565 Core::RomId::const_span romId() const { return data.romId(); } 00566 00567 /// Set ROM ID. 00568 WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { 00569 data.setRomId(romId); 00570 return *this; 00571 } 00572 00573 /// Set ROM ID for use in anonymous mode. 00574 WriteAuthenticationData & setAnonymousRomId() { 00575 data.setAnonymousRomId(); 00576 return *this; 00577 } 00578 00579 /// @} 00580 00581 /// @name Old page 00582 /// @brief Existing data contained in the page. 00583 /// @{ 00584 00585 /// Get mutable old page. 00586 Page::span oldPage() { return data.page(); } 00587 00588 /// Get immutable old page. 00589 Page::const_span oldPage() const { return data.page(); } 00590 00591 /// Set old page. 00592 WriteAuthenticationData & setOldPage(Page::const_span oldPage) { 00593 data.setPage(oldPage); 00594 return *this; 00595 } 00596 00597 /// @} 00598 00599 /// @name New page 00600 /// @brief New data to write to the page. 00601 /// @{ 00602 00603 /// Get mutable new page. 00604 Page::span newPage() { return data.challenge(); } 00605 00606 /// Get immutable new page. 00607 Page::const_span newPage() const { return data.challenge(); } 00608 00609 /// Set new page. 00610 WriteAuthenticationData & setNewPage(Page::const_span newPage) { 00611 data.setChallenge(newPage); 00612 return *this; 00613 } 00614 00615 /// @} 00616 00617 /// @name Page number 00618 /// @brief Page number for write operation. 00619 /// @{ 00620 00621 /// Get page number. 00622 int pageNum() const { return data.pageNum(); } 00623 00624 /// Set page number. 00625 WriteAuthenticationData & setPageNum(int pageNum) { 00626 data.setPageNum(pageNum); 00627 return *this; 00628 } 00629 00630 /// @} 00631 00632 /// @name MAN ID 00633 /// @brief Manufacturer ID of the device. 00634 /// @{ 00635 00636 /// Get mutable MAN ID. 00637 Core::ManId::span manId() { return data.manId(); } 00638 00639 /// Get immutable MAN ID. 00640 Core::ManId::const_span manId() const { return data.manId(); } 00641 00642 /// Set MAN ID. 00643 WriteAuthenticationData & setManId(Core::ManId::const_span manId) { 00644 data.setManId(manId); 00645 return *this; 00646 } 00647 00648 /// @} 00649 00650 private: 00651 PageAuthenticationData data; 00652 }; 00653 00654 /// Format compute secret input data. 00655 class DS28C36::ComputeSecretData { 00656 public: 00657 typedef PageAuthenticationData::Result Result; 00658 00659 ComputeSecretData() : data() {} 00660 00661 /// Formatted data result. 00662 Result::const_span result() const { return data.result(); } 00663 00664 /// @name ROM ID 00665 /// @brief 1-Wire ROM ID of the device. 00666 /// @{ 00667 00668 /// Get mutable ROM ID. 00669 Core::RomId::span romId() { return data.romId(); } 00670 00671 /// Get immutable ROM ID. 00672 Core::RomId::const_span romId() const { return data.romId(); } 00673 00674 /// Set ROM ID. 00675 ComputeSecretData & setRomId(Core::RomId::const_span romId) { 00676 data.setRomId(romId); 00677 return *this; 00678 } 00679 00680 /// @} 00681 00682 /// @name Binding Data 00683 /// @brief Binding Data contained in the selected page. 00684 /// @{ 00685 00686 /// Get mutable Binding Data. 00687 Page::span bindingData() { return data.page(); } 00688 00689 /// Get immutable Binding Data. 00690 Page::const_span bindingData() const { return data.page(); } 00691 00692 /// Set Binding Data. 00693 ComputeSecretData & setBindingData(Page::const_span bindingData) { 00694 data.setPage(bindingData); 00695 return *this; 00696 } 00697 00698 /// @} 00699 00700 /// @name Partial Secret 00701 /// @brief Partial Secret used for customization. 00702 /// @{ 00703 00704 /// Get mutable Partial Secret. 00705 Page::span partialSecret() { return data.challenge(); } 00706 00707 /// Get immutable Partial Secret. 00708 Page::const_span partialSecret() const { return data.challenge(); } 00709 00710 /// Set Partial Secret. 00711 ComputeSecretData & setPartialSecret(Page::const_span partialSecret) { 00712 data.setChallenge(partialSecret); 00713 return *this; 00714 } 00715 00716 /// @} 00717 00718 /// @name Page number 00719 /// @brief Page number for Binding Data. 00720 /// @{ 00721 00722 /// Get page number. 00723 int pageNum() const { return data.pageNum(); } 00724 00725 /// Set page number. 00726 ComputeSecretData & setPageNum(int pageNum) { 00727 data.setPageNum(pageNum); 00728 return *this; 00729 } 00730 00731 /// @} 00732 00733 /// @name MAN ID 00734 /// @brief Manufacturer ID of the device. 00735 /// @{ 00736 00737 /// Get mutable MAN ID. 00738 Core::ManId::span manId() { return data.manId(); } 00739 00740 /// Get immutable MAN ID. 00741 Core::ManId::const_span manId() const { return data.manId(); } 00742 00743 /// Set MAN ID. 00744 ComputeSecretData & setManId(Core::ManId::const_span manId) { 00745 data.setManId(manId); 00746 return *this; 00747 } 00748 00749 /// @} 00750 00751 private: 00752 PageAuthenticationData data; 00753 }; 00754 00755 /// Format encryption or decryption HMAC input data. 00756 class DS28C36::EncryptionHmacData { 00757 public: 00758 typedef Core::array_span<uint_least8_t, EncryptionChallenge::size + 00759 Core::RomId::size + 1 + 00760 Core::ManId::size> 00761 Result; 00762 00763 EncryptionHmacData() : result_() {} 00764 00765 /// Formatted data result. 00766 Result::const_span result() const { return result_; } 00767 00768 /// @name Encryption Challenge 00769 /// @brief Random challenge used to prevent replay attacks. 00770 /// @{ 00771 00772 /// Get mutable Encryption Challenge. 00773 EncryptionChallenge::span encryptionChallenge() { 00774 return make_span(result_) 00775 .subspan<encryptionChallengeIdx, EncryptionChallenge::size>(); 00776 } 00777 00778 /// Get immutable Encryption Challenge. 00779 EncryptionChallenge::const_span encryptionChallenge() const { 00780 return const_cast<EncryptionHmacData &>(*this).encryptionChallenge(); 00781 } 00782 00783 /// Set Encryption Challenge. 00784 EncryptionHmacData & 00785 setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { 00786 copy(encryptionChallenge, this->encryptionChallenge()); 00787 return *this; 00788 } 00789 00790 /// @} 00791 00792 /// @name ROM ID 00793 /// @brief 1-Wire ROM ID of the device. 00794 /// @{ 00795 00796 /// Get mutable ROM ID. 00797 Core::RomId::span romId() { 00798 return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); 00799 } 00800 00801 /// Get immutable ROM ID. 00802 Core::RomId::const_span romId() const { 00803 return const_cast<EncryptionHmacData &>(*this).romId(); 00804 } 00805 00806 /// Set ROM ID. 00807 EncryptionHmacData & setRomId(Core::RomId::const_span romId) { 00808 copy(romId, this->romId()); 00809 return *this; 00810 } 00811 00812 /// Set ROM ID for use in anonymous mode. 00813 MaximInterfaceDevices_EXPORT EncryptionHmacData & setAnonymousRomId(); 00814 00815 /// @} 00816 00817 /// @name Page number 00818 /// @brief Number of the page to use data from. 00819 /// @{ 00820 00821 /// Get page number. 00822 int pageNum() const { return result_[pageNumIdx]; } 00823 00824 /// Set page number. 00825 EncryptionHmacData & setPageNum(int pageNum) { 00826 result_[pageNumIdx] = pageNum; 00827 return *this; 00828 } 00829 00830 /// @} 00831 00832 /// @name MAN ID 00833 /// @brief Manufacturer ID of the device. 00834 /// @{ 00835 00836 /// Get mutable MAN ID. 00837 Core::ManId::span manId() { 00838 return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); 00839 } 00840 00841 /// Get immutable MAN ID. 00842 Core::ManId::const_span manId() const { 00843 return const_cast<EncryptionHmacData &>(*this).manId(); 00844 } 00845 00846 /// Set MAN ID. 00847 EncryptionHmacData & setManId(Core::ManId::const_span manId) { 00848 copy(manId, this->manId()); 00849 return *this; 00850 } 00851 00852 /// @} 00853 00854 private: 00855 static const size_t encryptionChallengeIdx = 0; 00856 static const size_t romIdIdx = 00857 encryptionChallengeIdx + EncryptionChallenge::size; 00858 static const size_t pageNumIdx = romIdIdx + Core::RomId::size; 00859 static const size_t manIdIdx = pageNumIdx + 1; 00860 00861 Result::array result_; 00862 }; 00863 00864 /// Access fields in the ROM Options page. 00865 class DS28C36::RomOptions { 00866 public: 00867 explicit RomOptions(Page::span page) : page(page) {} 00868 00869 bool romBlockDisable() const { 00870 return page[romBlockDisableIdx] == enabledValue; 00871 } 00872 00873 RomOptions & setRomBlockDisable(bool romBlockDisable) { 00874 page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0); 00875 return *this; 00876 } 00877 00878 bool anonymous() const { return page[anonymousIdx] == enabledValue; } 00879 00880 RomOptions & setAnonymous(bool anonymous) { 00881 page[anonymousIdx] = (anonymous ? enabledValue : 0); 00882 return *this; 00883 } 00884 00885 Core::ManId::const_span manId() const { 00886 return page.subspan<22, Core::ManId::size>(); 00887 } 00888 00889 Core::RomId::const_span romId() const { 00890 return page.subspan<24, Core::RomId::size>(); 00891 } 00892 00893 private: 00894 static const Page::span::index_type romBlockDisableIdx = 0; 00895 static const Page::span::index_type anonymousIdx = 1; 00896 static const Page::span::value_type enabledValue = 0xAA; 00897 00898 Page::span page; 00899 }; 00900 00901 /// Access fields in the GPIO Control page. 00902 class DS28C36::GpioControl { 00903 public: 00904 explicit GpioControl(Page::span page) : page(page) {} 00905 00906 bool pioaConducting() const { 00907 return page[pioaConductingIdx] == pioConductingValue; 00908 } 00909 00910 GpioControl & setPioaConducting(bool pioaConducting) { 00911 page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55); 00912 return *this; 00913 } 00914 00915 bool piobConducting() const { 00916 return page[piobConductingIdx] == pioConductingValue; 00917 } 00918 00919 GpioControl & setPiobConducting(bool piobConducting) { 00920 page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55); 00921 return *this; 00922 } 00923 00924 bool pioaLevel() const { return page[2] == pioLevelValue; } 00925 00926 bool piobLevel() const { return page[3] == pioLevelValue; } 00927 00928 private: 00929 static const Page::span::index_type pioaConductingIdx = 0; 00930 static const Page::span::index_type piobConductingIdx = 1; 00931 static const Page::span::value_type pioConductingValue = 0xAA; 00932 static const Page::span::value_type pioLevelValue = 0x55; 00933 00934 Page::span page; 00935 }; 00936 00937 } // namespace MaximInterfaceDevices 00938 00939 #endif
Generated on Tue Jul 12 2022 11:13:08 by 1.7.2