Aleksandrs Gumenuks / MaximInterface_Extended

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS28E38.hpp Source File

DS28E38.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_DS28E38
00034 #define MaximInterface_DS28E38
00035 
00036 #include <stdint.h>
00037 #include <MaximInterface/Links/RunCommand.hpp>
00038 #include <MaximInterface/Utilities/array_span.hpp>
00039 #include <MaximInterface/Utilities/Ecc256.hpp>
00040 #include <MaximInterface/Utilities/Export.h>
00041 #include <MaximInterface/Utilities/FlagSet.hpp>
00042 #include <MaximInterface/Utilities/ManId.hpp>
00043 #include <MaximInterface/Utilities/system_error.hpp>
00044 
00045 namespace MaximInterface {
00046 
00047 class DS28E38 {
00048 public:
00049   /// Device command results.
00050   enum ErrorValue {
00051     InvalidOperationError = 0x55,
00052     InvalidParameterError = 0x77,
00053     InvalidSequenceError = 0x33,
00054     InternalError = 0x22,
00055     DeviceDisabledError = 0x88,
00056     InvalidResponseError =
00057         0x100 ///< Command response does not match expected format.
00058   };
00059 
00060   /// @name Device memory pages
00061   /// @{
00062   
00063   static const int decrementCounterPage = 3;
00064   static const int publicKeyXPage = 4;
00065   static const int publicKeyYPage = 5;
00066   static const int privateKeyPage = 6;
00067   
00068   /// @}
00069 
00070   static const int memoryPages = 7;
00071 
00072   /// Holds a device memory page.
00073   typedef array_span<uint_least8_t, 32> Page;
00074 
00075   // Format page authentication input data.
00076   class PageAuthenticationData;
00077 
00078   /// Page protection types.
00079   enum PageProtectionType {
00080     RP = 0x01, ///< Read protection.
00081     WP = 0x02, ///< Write protection.
00082     EM = 0x04, ///< EPROM emulation mode.
00083     DC = 0x08, ///< Decrement counter.
00084     PF = 0x10  ///< PUF used as private key.
00085   };
00086   typedef FlagSet<PageProtectionType, 5> PageProtection;
00087 
00088   struct Status {
00089     enum EntropyHealthTestStatus {
00090       TestNotPerformed = 0xFF,
00091       EntropyHealthy = 0xAA,
00092       EntropyNotHealthy = 0xDD
00093     };
00094 
00095     typedef array<PageProtection, memoryPages> PageProtectionList;
00096     typedef array<uint_least8_t, 2> RomVersion;
00097 
00098     PageProtectionList pageProtection;
00099     ManId::array manId;
00100     RomVersion romVersion;
00101     EntropyHealthTestStatus entropyHealthTestStatus;
00102   };
00103 
00104   explicit DS28E38(const RunCommand & runCommand) : doRunCommand(runCommand) {}
00105 
00106   void setRunCommand(const RunCommand & runCommand) {
00107     doRunCommand = runCommand;
00108   }
00109 
00110   /// @brief Write memory with no protection.
00111   /// @param pageNum Number of page to write.
00112   /// @param page Data to write.
00113   MaximInterface_EXPORT error_code writeMemory(int pageNum,
00114                                                Page::const_span page);
00115 
00116   /// @brief Read memory with no protection.
00117   /// @param pageNum Number of page to read.
00118   /// @param[out] page Data that was read.
00119   MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page);
00120 
00121   /// @brief
00122   /// Reads the current status of the device and optionally performs an
00123   /// entropy health test.
00124   /// @param entropyHealthTest True to perform an entropy health test.
00125   /// @param[out] status Status that was read.
00126   MaximInterface_EXPORT error_code readStatus(bool entropyHealthTest,
00127                                               Status & status);
00128 
00129   /// @brief Set the protection settings of a page.
00130   /// @param pageNum Number of page to write.
00131   /// @param protection Protection to write.
00132   MaximInterface_EXPORT error_code
00133   setPageProtection(int pageNum, const PageProtection & protection);
00134 
00135   /// @brief Compute and read page authentication with ECDSA.
00136   /// @param pageNum Number of page to authenticate.
00137   /// @param anonymous True to disable use of ROM ID in computation.
00138   /// @param challenge Random challenge used to prevent replay attacks.
00139   /// @param[out] signature Computed page signature.
00140   MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
00141       int pageNum, bool anonymous, Page::const_span challenge,
00142       Ecc256::Signature::span signature);
00143 
00144   /// Decrement the decrement-only counter.
00145   MaximInterface_EXPORT error_code decrementCounter();
00146 
00147   /// Permanently disable the device.
00148   MaximInterface_EXPORT error_code disableDevice();
00149 
00150   /// @brief Generate a new ECDSA public key from an existing private key.
00151   /// @param privateKeyPuf True if PUF is used as the private key.
00152   /// @param writeProtectEnable True to lock the key against further writes.
00153   MaximInterface_EXPORT error_code
00154   generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable);
00155 
00156   /// @brief Read a block of random data from the RNG.
00157   /// @param[out] data Random data from RNG with length from 1 to 64.
00158   MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
00159 
00160   MaximInterface_EXPORT static const error_category & errorCategory();
00161 
00162 protected:
00163   MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command,
00164                                               int delayTime,
00165                                               span<uint_least8_t> & response);
00166 
00167   MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command,
00168                                               int delayTime);
00169 
00170 private:
00171   RunCommand doRunCommand;
00172 };
00173 
00174 inline error_code make_error_code(DS28E38::ErrorValue e) {
00175   return error_code(e, DS28E38::errorCategory());
00176 }
00177 
00178 /// @brief Read the device MAN ID using the Read Status command.
00179 /// @param ds28e38 Device to read.
00180 /// @param[out] manId Read MAN ID valid when operation is successful.
00181 MaximInterface_EXPORT error_code readManId(DS28E38 & ds28e38,
00182                                            ManId::span manId);
00183 
00184 /// Format page authentication input data.
00185 class DS28E38::PageAuthenticationData {
00186 public:
00187   typedef array_span<uint_least8_t,
00188                      RomId::size + 2 * Page::size + 1 + ManId::size>
00189       Result;
00190 
00191   PageAuthenticationData() : result_() {}
00192 
00193   /// Formatted data result.
00194   Result::const_span result() const { return result_; }
00195 
00196   /// @name ROM ID
00197   /// @brief 1-Wire ROM ID of the device.
00198   /// @{
00199   
00200   /// Get mutable ROM ID.
00201   RomId::span romId() {
00202     return make_span(result_).subspan<romIdIdx, RomId::size>();
00203   }
00204   
00205   /// Get immutable ROM ID.
00206   RomId::const_span romId() const {
00207     return const_cast<PageAuthenticationData &>(*this).romId();
00208   }
00209   
00210   /// Set ROM ID.
00211   PageAuthenticationData & setRomId(RomId::const_span romId) {
00212     copy(romId, this->romId());
00213     return *this;
00214   }
00215   
00216   /// Set ROM ID for use in anonymous mode.
00217   MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
00218   
00219   /// @}
00220 
00221   /// @name Page
00222   /// @brief Data from a device memory page.
00223   /// @{
00224   
00225   /// Get mutable page.
00226   Page::span page() {
00227     return make_span(result_).subspan<pageIdx, Page::size>();
00228   }
00229   
00230   /// Get immutable page.
00231   Page::const_span page() const {
00232     return const_cast<PageAuthenticationData &>(*this).page();
00233   }
00234   
00235   /// Set page.
00236   PageAuthenticationData & setPage(Page::const_span page) {
00237     copy(page, this->page());
00238     return *this;
00239   }
00240   
00241   /// @}
00242 
00243   /// @name Challenge
00244   /// @brief Random challenge used to prevent replay attacks.
00245   /// @{
00246 
00247   /// Get mutable Challenge.
00248   Page::span challenge() {
00249     return make_span(result_).subspan<challengeIdx, Page::size>();
00250   }
00251   
00252   /// Get immutable Challenge.
00253   Page::const_span challenge() const {
00254     return const_cast<PageAuthenticationData &>(*this).challenge();
00255   }
00256   
00257   /// Set Challenge.
00258   PageAuthenticationData & setChallenge(Page::const_span challenge) {
00259     copy(challenge, this->challenge());
00260     return *this;
00261   }
00262   
00263   /// @}
00264 
00265   /// @name Page number
00266   /// @brief Number of the page to use data from.
00267   /// @{
00268   
00269   /// Get page number.
00270   int pageNum() const { return result_[pageNumIdx]; }
00271   
00272   /// Set page number.
00273   PageAuthenticationData & setPageNum(int pageNum) {
00274     result_[pageNumIdx] = pageNum;
00275     return *this;
00276   }
00277   
00278   /// @}
00279 
00280   /// @name MAN ID
00281   /// @brief Manufacturer ID of the device.
00282   /// @{
00283   
00284   /// Get mutable MAN ID.
00285   ManId::span manId() {
00286     return make_span(result_).subspan<manIdIdx, ManId::size>();
00287   }
00288   
00289   /// Get immutable MAN ID.
00290   ManId::const_span manId() const {
00291     return const_cast<PageAuthenticationData &>(*this).manId();
00292   }
00293   
00294   /// Set MAN ID.
00295   PageAuthenticationData & setManId(ManId::const_span manId) {
00296     copy(manId, this->manId());
00297     return *this;
00298   }
00299   
00300   /// @}
00301 
00302 private:
00303   typedef Result::span::index_type index;
00304 
00305   static const index romIdIdx = 0;
00306   static const index pageIdx = romIdIdx + RomId::size;
00307   static const index challengeIdx = pageIdx + Page::size;
00308   static const index pageNumIdx = challengeIdx + Page::size;
00309   static const index manIdIdx = pageNumIdx + 1;
00310 
00311   Result::array result_;
00312 };
00313 
00314 } // namespace MaximInterface
00315 
00316 #endif