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 DS28E38.hpp Source File

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