Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS28E83_DS28E84.hpp Source File

DS28E83_DS28E84.hpp

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