1-Wire® library for mbed. Complete 1-Wire library that supports our silicon masters along with a bit-bang master on the MAX32600MBED platform with one common interface for mbed. Slave support has also been included and more slaves will be added as time permits.

Dependents:   MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more

Superseded by MaximInterface.

OneWire_Memory/Authenticators/DS28E15_22_25/DS28E15_22_25.hpp

Committer:
IanBenzMaxim
Date:
2016-04-08
Revision:
49:36954b62f503
Parent:
34:11fffbe98ef9
Child:
50:e967f9befbd0

File content as of revision 49:36954b62f503:

//------------Copyright (C) 2013 Maxim Integrated Products --------------
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL MAXIM INTEGRATED PRODCUTS BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of Maxim Integrated Products
// shall not be used except as stated in the Maxim Integrated Products
// Branding Policy.
// ---------------------------------------------------------------------------

#ifndef DS28E15_22_25_H
#define DS28E15_22_25_H

#include "array.hpp"
#include "OneWire_Masters/ISha256MacCoprocessor.hpp"
#include "OneWireSlave.hpp"

class OneWireMaster;

/// Interface to the DS28E15/22/25 series of authenticators
/// including low power variants.
class DS28E15_22_25 : public OneWireSlave
{
public:
  /// Family code for each device.
  enum FamilyCode
  {
    DS28E25_FAMILY = 0x47,
    DS28E22_FAMILY = 0x48,
    DS28E15_FAMILY = 0x17,
    UNKNOWN_FAMILY = 0
  };

  /// Number for memory pages for each device.
  enum MemoryPages
  {
    DS28E25_PAGES = 16,
    DS28E22_PAGES = 8,
    DS28E15_PAGES = 2,
    UNKNOWN_PAGES = 0
  };
  
  /// Number of protection blocks for each device.
  enum ProtectionBlocks
  {
    DS28E25_BLOCKS = 8,
    DS28E22_BLOCKS = 4,
    DS28E15_BLOCKS = 4,
    UNKNOWN_BLOCKS = 0
  };
  
  /// Holds the contents of a device memory page.
  typedef array<std::uint8_t, 32> Page;
  
  /// Holds the contents of the device scratchpad.
  typedef array<std::uint8_t, 32> Scratchpad;
  
  /// Container for a SHA-256 MAC.
  typedef array<std::uint8_t, 32> Mac;
  
  /// Holds the contents of a device memory segment.
  typedef array<std::uint8_t, 4> Segment;
  
  /// Container for a manufacturer ID.
  typedef array<std::uint8_t, 2> ManId;
  
  /// Represents the status of a memory protection block.
  class BlockProtection
  {
  private:
    static const std::uint8_t readProtectionMask = 0x80, writeProtectionMask = 0x40, eepromEmulationMask = 0x20, authProtectionMask = 0x10, blockNumMask = 0x03;
    std::uint8_t m_status;
    
  public:
    BlockProtection() : m_status(0x00) { }
    BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, std::uint8_t blockNum);
  
    /// Get the byte representation used by the device.
    std::uint8_t statusByte() const { return m_status; }
    /// Set the byte representation used by the device.
    void setStatusByte(std::uint8_t status) { m_status = status; }
    
    /// Get the Block Number which is indexed from zero.
    std::uint8_t blockNum() const { return (m_status & blockNumMask); }
    /// Set the Block Number which is indexed from zero.
    void setBlockNum(std::uint8_t blockNum);
  
    /// Get the Read Protection status.
    /// @returns True if Read Protection is enabled.
    bool readProtection() const { return ((m_status & readProtectionMask) == readProtectionMask); }
    /// Set the Read Protection status.
    void setReadProtection(bool readProtection);
    
    /// Get the Write Protection status.
    /// @returns True if Write Protection is enabled.
    bool writeProtection() const { return ((m_status & writeProtectionMask) == writeProtectionMask); }
    /// Set the Write Protection status.
    void setWriteProtection(bool writeProtection);
    
    /// Get the EEPROM Emulation Mode status.
    /// @returns True if EEPROM Emulation Mode is enabled.
    bool eepromEmulation() const { return ((m_status & eepromEmulationMask) == eepromEmulationMask); }
    /// Set the EEPROM Emulation Mode status.
    void setEepromEmulation(bool eepromEmulation);
    
    /// Get the Authentication Protection status.
    /// @returns True if Authentication Protection is enabled.
    bool authProtection() const { return ((m_status & authProtectionMask) == authProtectionMask); }
    /// Set the Authentication Protection status.
    void setAuthProtection(bool authProtection);
    
    /// Check if no protection options are enabled.
    /// @returns True if no protection options are enabled.
    bool noProtection() const;
    
    bool operator==(const BlockProtection & rhs) const { return (this->m_status == rhs.m_status); }
    bool operator!=(const BlockProtection & rhs) const { return !operator==(rhs); }
  };
  
  /// Compute the MAC for an Authenticated Write to a memory segment.
  /// @param MacCoproc Coprocessor with Slave Secret to use for the computation.
  /// @param pageNum Page number for write operation.
  /// @param segmentNum Segment number within page for write operation.
  /// @param[in] newData New data to write to the segment.
  /// @param[in] oldData Existing data contained in the segment.
  /// @param[in] romId 1-Wire ROM ID of the device.
  /// @param[in] manId Manufacturer ID of the device.
  /// @param[out] mac The computed MAC.
  /// @returns The result code indicated by the coprocessor.
  static ISha256MacCoprocessor::CmdResult computeSegmentWriteMac(const ISha256MacCoprocessor & MacCoproc,
                                                                 unsigned int pageNum,
                                                                 unsigned int segmentNum,
                                                                 const Segment & newData,
                                                                 const Segment & oldData,
                                                                 const RomId & romId,
                                                                 const ManId & manId,
                                                                 Mac & mac);
                                                                   
  /// Compute the MAC for an Authenticated Write to a memory protection block.
  /// @param MacCoproc Coprocessor with Slave Secret to use for the operation.
  /// @param[in] newProtection New protection status to write.
  /// @param[in] oldProtection Existing protection status in device.
  /// @param[in] romId 1-Wire ROM ID of the device.
  /// @param[in] manId Manufacturer ID of the device.
  /// @param[out] mac The computed MAC.
  /// @returns The result code indicated by the coprocessor.
  static ISha256MacCoprocessor::CmdResult computeProtectionWriteMac(const ISha256MacCoprocessor & MacCoproc,
                                                                    const BlockProtection & newProtection,
                                                                    const BlockProtection & oldProtection,
                                                                    const RomId & romId,
                                                                    const ManId & manId,
                                                                    Mac & mac);
  
  /// Compute the next secret from the existing secret.
  /// @param MacCoproc Coprocessor with Master Secret to use for the operation.
  ///        Slave Secret will be updated with the computation result.
  /// @param[in] bindingPage Binding data from a device memory page.
  /// @param bindingPageNum Number of the page where the binding data is from.
  /// @param[in] partialSecret Partial secret data from the device scratchpad.
  /// @param[in] romId 1-Wire ROM ID of the device.
  /// @param[in] manId Manufacturer ID of the device.
  /// @returns The result code indicated by the coprocessor.
  static ISha256MacCoprocessor::CmdResult computeNextSecret(ISha256MacCoprocessor & MacCoproc,
                                                            const Page & bindingPage,
                                                            unsigned int bindingPageNum,
                                                            const Scratchpad & partialSecret,
                                                            const RomId & romId,
                                                            const ManId & manId);
  
  /// Compute a Page MAC for authentication.
  /// @param MacCoproc Coprocessor with Slave Secret to use for the operation.
  /// @param[in] pageData Data from a device memory page.
  /// @param pageNum Number of the page to use data from.
  /// @param[in] challenge Random challenge to prevent replay attacks.
  /// @param[in] romId 1-Wire ROM ID of the device.
  /// @param[in] manId Manufacturer ID of the device.
  /// @param[out] mac The computed MAC.
  static ISha256MacCoprocessor::CmdResult computeAuthMac(const ISha256MacCoprocessor & MacCoproc,
                                                         const Page & pageData,
                                                         unsigned int pageNum,
                                                         const Scratchpad & challenge,
                                                         const RomId & romId,
                                                         const ManId & manId,
                                                         Mac & mac);
                                                         
  /// Compute a Page MAC for authentication using anonymous mode.
  /// @param MacCoproc Coprocessor with Slave Secret to use for the operation.
  /// @param[in] pageData Data from a device memory page.
  /// @param pageNum Number of the page to use data from.
  /// @param[in] challenge Random challenge to prevent replay attacks.
  /// @param[in] manId Manufacturer ID of the device.
  /// @param[out] mac The computed MAC.
  static ISha256MacCoprocessor::CmdResult computeAuthMacAnon(const ISha256MacCoprocessor & MacCoproc,
                                                             const Page & pageData,
                                                             unsigned int pageNum,
                                                             const Scratchpad & challenge,
                                                             const ManId & manId,
                                                             Mac & mac);
  
  /// Manufacturer ID
  ManId manId;
  
  /// Enable low voltage timing
  bool lowVoltage;
  
  /// @param OW_master 1-Wire Master to use for communication with DS28E15/22/25.
  /// @param lowVoltage Enable low voltage timing.
  DS28E15_22_25(OneWireMaster & OW_master, bool lowVoltage = false);
  
  // Const member functions should not affect the state of the memory, block protection, or secret on the DS28Exx.
  // Scratchpad on the DS28Exx is considered mutable.

  /// Get the number of memory pages from the ROM ID of this device.
  MemoryPages memoryPages();
  
  /// Get the number of protection blocks from the ROM ID of this device.
  ProtectionBlocks protectionBlocks();
  
  /// Perform Load and Lock Secret command on the device.
  /// @note The secret should already be stored in the scratchpad on the device.
  /// @param lock Prevent further changes to the secret on the device after loading.
  CmdResult loadSecret(bool lock);
  
  /// Perform Write Scratchpad operation on the device.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param[in] data Data to write to the scratchpad.
  CmdResult writeScratchpad(const Scratchpad & data) const;
  
  /// Perform a Read Scratchpad operation on the device.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param[out] data Buffer to read data from the scratchpad into.
  CmdResult readScratchpad(Scratchpad & data) const;
  
  /// Read memory segment using the Read Memory command on the device.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param pageNum Page number for read operation.
  /// @param segmentNum Segment number within page for read operation.
  /// @param[out] data Buffer to read data from the segment into.
  CmdResult readSegment(unsigned int pageNum, unsigned int segmentNum, Segment & data) const;
  
  /// Write memory segment using the Write Memory command.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param pageNum Page number for write operation.
  /// @param segmentNum Segment number within page for write operation.
  /// @param[in] data Data to write to the memory segment.
  /// @param continuing True to continue writing with the next sequential segment.
  ///                   False to begin a new command.
  CmdResult writeSegment(unsigned int pageNum, unsigned int segmentNum, const Segment & data, bool continuing = false);
  
  /// Read memory page using the Read Memory command on the device.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param pageNum Page number for write operation.
  /// @param[out] rdbuf Buffer to read data from the page into.
  /// @param continuing True if continuing a previous Read Memory command.
  ///                   False to begin a new command.
  CmdResult readPage(unsigned int pageNum, Page & rdbuf, bool continuing = false) const;
  
  /// Perform a Compute and Lock Secret command on the device.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param pageNum Page number to use as the binding data.
  /// @param lock Prevent further changes to the secret on the device after computing.
  CmdResult computeSecret(unsigned int pageNum, bool lock);
  
  /// Perform a Compute Page MAC command on the device.
  /// Read back the MAC and verify the CRC16.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param pageNum Page number to use for the computation.
  /// @param anon True to compute in anonymous mode where ROM ID is not used.
  /// @param[out] mac The device computed MAC.
  CmdResult computeReadPageMac(unsigned int pageNum, bool anon, Mac & mac) const;
  
  /// Read the status of a memory protection block using the Read Status command.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param blockNum Block number to to read status of.
  /// @param[out] protection Receives protection status read from device.
  CmdResult readBlockProtection(unsigned int blockNum, BlockProtection & protection);
  
  /// Update the status of a memory protection block using the Write Page Protection command.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param[in] Desired protection status for the block.
  ///            It is not possible to disable existing protections.
  /// @param continuing True to continue a previous Write Page Protection command.
  ///                   False to begin a new command.
  CmdResult writeBlockProtection(const BlockProtection & protection, bool continuing = false);
  
  /// Update the status of a memory protection block using the Authenticated Write Page Protection command.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param MacCoproc Coprocessor with Slave Secret to use for the operation.
  /// @param[in] newProtection New protection status to write.
  /// @param[in] oldProtection Existing protection status in device.
  /// @param continuing True to continue a previous Authenticated Write Page Protection command.
  ///                   False to begin a new command.
  CmdResult writeAuthBlockProtection(const ISha256MacCoprocessor & MacCoproc,
                                     const BlockProtection & newProtection,
                                     const BlockProtection & oldProtection,
                                     bool continuing = false);
  
  /// Write memory segment with authentication using the Authenticated Write Memory command.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param MacCoproc Coprocessor to use for Write MAC computation.
  /// @param pageNum Page number for write operation.
  /// @param segmentNum Segment number within page for write operation.
  /// @param[in] newData New data to write to the segment.
  /// @param[in] oldData Existing data contained in the segment.
  /// @param continuing True to continue writing with the next sequential segment.
  ///                   False to begin a new command.
  CmdResult writeAuthSegment(const ISha256MacCoprocessor & MacCoproc,
                             unsigned int pageNum,
                             unsigned int segmentNum,
                             const Segment & newData,
                             const Segment & oldData,
                             bool continuing = false);
  
  /// Write memory segment with authentication using the Authenticated Write Memory command.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param pageNum Page number for write operation.
  /// @param segmentNum Segment number within page for write operation.
  /// @param[in] newData New data to write to the segment.
  /// @param[in] mac Write MAC computed for this operation.
  /// @param continuing True to continue writing with the next sequential segment.
  ///                   False to begin a new command.
  CmdResult writeAuthSegmentMac(unsigned int pageNum,
                                unsigned int segmentNum,
                                const Segment & newData,
                                const Mac & mac, 
                                bool continuing = false);
  
private: 
  static const unsigned int shaComputationDelayMs = 3;
  static const unsigned int eepromWriteDelayMs = 10;
  unsigned int secretEepromWriteDelayMs() const { return (lowVoltage ? 200 : 100); }

  OneWireMaster & m_OW_master;
  
  /// Read status bytes which are either personality or block protection.
  /// @note 1-Wire ROM selection should have already occurred.
  /// @param personality True to read personality or false to read block protection.
  /// @param allpages True to read all pages or false to read one page.
  /// @param pageNum Page number if reading block protection.
  /// @param rdbuf Buffer to receive data read from device.
  CmdResult readStatus(bool personality, bool allpages, unsigned int pageNum, std::uint8_t * rdbuf) const;
};

#endif