Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MaximInterface
DS28C36.hpp
- Committer:
- IanBenzMaxim
- Date:
- 2017-04-06
- Revision:
- 9:40dd19da90c3
- Parent:
- 0:33d4e66780c0
File content as of revision 9:40dd19da90c3:
/*******************************************************************************
* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
*
* 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 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, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************/
#ifndef DS28C36_HPP
#define DS28C36_HPP
#include <vector>
#include "array.h"
namespace mbed { class I2C; }
namespace OneWire { class RomId; }
/// Interface to the DS28C36 authenticator.
class DS28C36
{
public:
/// Device command results.
enum CmdResult
{
Success = 0xAA,
ProtectionError = 0x55,
InvalidParameterError = 0x77,
InvalidSequenceError = 0x33,
InvalidEcdsaInputOrResultError = 0x22,
AuthenticationError = 0x00,
CommunicationError = 0xFF ///< Special code for I2C communication error.
};
/// Device memory pages.
enum PageNum
{
UserData0 = 0,
UserData1,
UserData2,
UserData3,
UserData4,
UserData5,
UserData6,
UserData7,
UserData8,
UserData9,
UserData10,
UserData11,
UserData12,
UserData13,
UserData14,
UserData15,
PublicKeyAX,
PublicKeyAY,
PublicKeyBX,
PublicKeyBY,
PublicKeyCX,
PublicKeyCY,
PrivateKeyA,
PrivateKeyB,
PrivateKeyC,
SecretA,
SecretB,
DecrementCounter,
RomOptions,
GpioControl,
PublicKeySX,
PublicKeySY
};
/// Available keys for ECDSA operations.
enum KeyNum
{
KeyNumA = 0,
KeyNumB = 1,
KeyNumC = 2,
KeyNumS = 3
};
/// Available secrets for HMAC operations.
enum SecretNum
{
SecretNumA = 0,
SecretNumB = 1,
SecretNumS = 2
};
/// Data hash type when verifying an ECDSA signature.
enum HashType
{
HashInBuffer = 0, ///< Hash is loaded in the buffer.
DataInBuffer = 1, ///< Compute hash from data loaded in the buffer.
THASH = 2 ///< Use THASH from Compute Multiblock Hash command.
};
/// Available PIO states when verifying an ECDSA signature.
enum PioState
{
Unchanged,
Conducting,
HighImpedance
};
typedef OneWire::array<uint8_t, 32> Page; ///< Holds a device memory page.
typedef OneWire::array<uint8_t, 32> HMAC; ///< Holds a computed HMAC.
typedef std::vector<uint8_t> Buffer; ///< Holds a variable length device buffer.
/// Holds a computed ECDSA signature.
struct Signature
{
Page r;
Page s;
};
/// Holds an encrypted device memory page.
struct EncryptedPage
{
OneWire::array<uint8_t, 8> challenge;
Page data;
};
/// Holds the protection status of a memory page.
class PageProtection
{
public:
/// Page protection types.
enum Protection
{
RP = 0x01, ///< Read protection.
WP = 0x02, ///< Write protection.
EM = 0x04, ///< EPROM emulation mode.
APH = 0x08, ///< Authentication write protection HMAC.
EPH = 0x10, ///< Encryption and authenticated write protection HMAC.
AUTH = 0x20, ///< Public Key C is set to authority public key.
ECH = 0x40, ///< Encrypted read and write using shared key from ECDH.
ECW = 0x80 ///< Authentication write protection ECDSA.
};
explicit PageProtection(uint8_t status = 0x00) : m_status(status) { }
/// @{
/// Byte representation used by the device.
uint8_t statusByte() const { return m_status; }
void setStatusByte(uint8_t status) { m_status = status; }
/// @}
/// @{
/// Get/set whether a protection type is enabled.
bool protectionEnabled(Protection protection) const
{
return ((m_status & protection) == protection);
}
void setProtectionEnabled(Protection protection, bool enabled)
{
if (enabled) { m_status |= protection; }
else { m_status &= ~protection; }
}
/// @}
bool operator==(const PageProtection & rhs) const { return this->m_status == rhs.m_status; }
bool operator!=(const PageProtection & rhs) const { return !operator==(rhs); }
private:
uint8_t m_status;
};
explicit DS28C36(mbed::I2C & i2c, uint8_t i2cAddress = 0x36) :
m_i2c(i2c), m_i2cAddress(i2cAddress) { }
/// Write memory with no protection.
/// @param pageNum Number of page to write.
/// @param page Data to write.
CmdResult writeMemory(int pageNum, const Page & page);
/// Read memory with no protection.
/// @param pageNum Number of page to read.
/// @param[out] page Data that was read.
CmdResult readMemory(int pageNum, Page & page);
/// Write the temporary buffer.
/// @param data Data to write.
CmdResult writeBuffer(const Buffer & data);
/// Read the temporary buffer.
/// @param[out] data Data that was read.
CmdResult readBuffer(Buffer & data);
/// Read the protection settings of a page.
/// @param pageNum Number of page to read.
/// @param[out] protection Protection that was read.
CmdResult readPageProtection(int pageNum, PageProtection & protection);
/// Set the protection settings of a page.
/// @param pageNum Number of page to write.
/// @param protection Protection to write.
CmdResult setPageProtection(int pageNum, const PageProtection & protection);
/// Decrement the decrement-only counter.
CmdResult decrementCounter();
/// Read a block of random data from the RNG.
/// @param numBytes Number of bytes to read from 1 to 64.
/// @param[out] data Random data from RNG.
CmdResult readRng(int numBytes, Buffer & data);
/// Read memory with encryption.
/// @param pageNum Number of page to read from.
/// @param secretNum Secret to use for encryption.
/// @param[out] page Data that was read.
CmdResult encryptedReadMemory(int pageNum, SecretNum secretNum, EncryptedPage & page);
/// Compute and read page authentication with ECDSA.
/// @param pageNum Number of page to authenticate.
/// @param keyNum Private key to use for authentication. Key S cannot be used with this command.
/// @param[out] signature Computed page signature.
CmdResult computeAndReadEcdsaPageAuthentication(int pageNum, KeyNum keyNum, Signature & signature);
/// Compute and read page authentication with HMAC.
/// @param pageNum Number of page to authenticate.
/// @param secretNum Secret to use for authentication.
/// @param[out] hmac Computed page HMAC.
CmdResult computeAndReadHmacPageAuthentication(int pageNum, SecretNum secretNum, HMAC & hmac);
/// Write with SHA2 authentication.
/// @param pageNum Number of page to write.
/// @param secretNum Secret to use for authentication.
/// @param page Data to write.
CmdResult authenticatedSha2WriteMemory(int pageNum, SecretNum secretNum, const Page & page);
/// Compute SHA2 secret and optionally lock.
/// @param pageNum Number of page to use in computation.
/// @param msecretNum Master secret to use in computation.
/// @param dsecretNum Destination secret to receive the computation result.
/// @param writeProtectEnable True to lock the destination secret against further writes.
CmdResult computeAndLockSha2Secret(int pageNum, SecretNum msecretNum, SecretNum dsecretNum, bool writeProtectEnable);
/// Generate a new ECDSA key pair.
/// @param keyNum Key to generate. Key S cannot be used with this command.
/// @param writeProtectEnable True to lock the key against further writes.
CmdResult generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
/// Compute a hash over multiple blocks.
/// @param firstBlock True if this is the first block being hashed.
/// @param lastBlock True if thisis the last block being hashed.
/// @param data Data block to hash. Length should be 64 bytes unless this is the last block.
CmdResult computeMultiblockHash(bool firstBlock, bool lastBlock, const Buffer & data);
/// Verify ECDSA signature.
/// @param keyNum Public key to use for verification.
/// @param hashType Source of the data hash input.
/// @param signature Signature to verify.
/// @param pioa New state of PIOA if verification successful.
/// @param piob New state of PIOB if verification successful.
CmdResult verifyEcdsaSignature(KeyNum keyNum, HashType hashType, const Signature & signature, PioState pioa = Unchanged, PioState piob = Unchanged);
/// Authenticate a public key for authenticated writes or encrypted reads with ECDH.
/// @param authWrites True to select authentication for writes.
/// @param ecdh True to select ECDH key exchange.
/// @param keyNum Private key to use for ECDH key exchange. Key A or B can be selected.
/// @param csOffset Certificate customization field ending offset in buffer.
/// @param signature Signature to use for authentication of public key S.
CmdResult authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum, int csOffset, const Signature & signature);
/// Write with ECDSA authentication.
/// @param pageNum Number of page to write.
/// @param page Data to write.
CmdResult authenticatedEcdsaWriteMemory(int pageNum, const Page & page);
/// Read the device ROM ID using the Read Memory command.
/// @param ds28c36 Device to read.
/// @param[out] romId Read ROM ID valid when operation is successful.
static CmdResult readRomId(DS28C36 & ds28c36, OneWire::RomId & romId);
protected:
// Timing constants.
static const int generateEcdsaSignatureTimeMs = 50;
static const int generateEccKeyPairTimeMs = 100;
static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150;
static const int sha256ComputationTimeMs = 3;
static const int readMemoryTimeMs = /*1*/ 2;
static const int writeMemoryTimeMs = 15;
static CmdResult convertResultByte(uint8_t resultByte);
CmdResult writeCommand(uint8_t command, const Buffer & parameters);
CmdResult readResponse(Buffer & response);
private:
enum AuthType
{
HmacWithSecretA = 0,
HmacWithSecretB = 1,
HmacWithSecretS = 2,
EcdsaWithKeyA = 3,
EcdsaWithKeyB = 4,
EcdsaWithKeyC = 5
};
static const int numPages = 32;
mbed::I2C & m_i2c;
uint8_t m_i2cAddress;
/// Compute any type of authentication on page.
/// @param pageNum Number of page to authenticate.
/// @param authType Method to use to compute authentication.
/// @param[out] data Raw computed page authentication.
CmdResult computeAndReadPageAuthentication(int pageNum, AuthType authType, Buffer & data);
};
#endif