Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS28C36_DS2476.hpp Source File

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