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