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 DS28E16.cpp Source File

DS28E16.cpp

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 #include <stddef.h>
00034 #include <algorithm>
00035 #include <MaximInterfaceCore/Error.hpp>
00036 #include "DS28E16.hpp"
00037 
00038 namespace MaximInterfaceDevices {
00039 
00040 using namespace Core;
00041 using std::copy;
00042 using std::fill;
00043 
00044 static const int readMemoryTimeMs = 5;
00045 static const int writeMemoryTimeMs = 60;
00046 static const int shortWriteMemoryTimeMs = 15;
00047 static const int computationTimeMs = 15;
00048 
00049 const int DS28E16::decrementCounterPage;
00050 const int DS28E16::masterSecretPage;
00051 const int DS28E16::memoryPages;
00052 
00053 Result<void> DS28E16::writeMemory(int pageNum, Page::const_span page) {
00054   if (pageNum < 0 || pageNum >= memoryPages) {
00055     return InvalidParameterError;
00056   }
00057 
00058   uint_least8_t request[2 + Page::size];
00059   request[0] = 0x96;
00060   request[1] = pageNum;
00061   copy(page.begin(), page.end(), request + 2);
00062   return runCommand(request, writeMemoryTimeMs);
00063 }
00064 
00065 Result<DS28E16::Page::array> DS28E16::readMemory(int pageNum) const {
00066   if (pageNum < 0 || pageNum >= memoryPages) {
00067     return InvalidParameterError;
00068   }
00069 
00070   uint_least8_t buffer[1 + Page::size * 2];
00071   buffer[0] = 0x44;
00072   buffer[1] = pageNum;
00073   Result<span<uint_least8_t> > response =
00074       runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
00075   if (!response) {
00076     return response.error();
00077   }
00078   Page::array page;
00079   response.value() = response.value().first(Page::size);
00080   copy(response.value().begin(), response.value().end(), page.begin());
00081   return page;
00082 }
00083 
00084 Result<DS28E16::Status> DS28E16::readStatus() const {
00085   uint_least8_t buffer[1 + Status::PageProtectionList::size + 2];
00086   buffer[0] = 0xAA;
00087   const Result<span<uint_least8_t> > response =
00088       runCommand(make_span(buffer, 1), readMemoryTimeMs, buffer);
00089   if (!response) {
00090     return response.error();
00091   }
00092   Status status;
00093   span<uint_least8_t>::const_iterator responseIt = response.value().begin();
00094   for (Status::PageProtectionList::array::iterator it =
00095            status.pageProtection.begin();
00096        it != status.pageProtection.end(); ++it) {
00097     *it = *responseIt;
00098     ++responseIt;
00099   }
00100   status.manId = *responseIt;
00101   ++responseIt;
00102   status.deviceVersion = *responseIt;
00103   return status;
00104 }
00105 
00106 Result<void> DS28E16::setPageProtection(int pageNum,
00107                                         const PageProtection & protection) {
00108   if (pageNum < 0 || pageNum >= memoryPages) {
00109     return InvalidParameterError;
00110   }
00111 
00112   const uint_least8_t request[] = {
00113       0xC3, static_cast<uint_least8_t>(pageNum),
00114       static_cast<uint_least8_t>(protection.to_ulong())};
00115   return runCommand(request, shortWriteMemoryTimeMs);
00116 }
00117 
00118 Result<DS28E16::DoublePage::array> DS28E16::computeAndReadPageAuthentication(
00119     int pageNum, bool anonymous, DoublePage::const_span challenge) const {
00120   if (pageNum < 0 || pageNum >= memoryPages) {
00121     return InvalidParameterError;
00122   }
00123 
00124   const size_t requestSize = 3 + DoublePage::size;
00125   const size_t responseSize = 1 + DoublePage::size;
00126   uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
00127   buffer[0] = 0xA5;
00128   buffer[1] = pageNum;
00129   if (anonymous) {
00130     buffer[1] |= 0xE0;
00131   }
00132   buffer[2] = 0x02;
00133   copy(challenge.begin(), challenge.end(), buffer + 3);
00134   const Result<span<uint_least8_t> > response =
00135       runCommand(make_span(buffer, requestSize), computationTimeMs,
00136                  make_span(buffer, responseSize));
00137   if (!response) {
00138     return response.error();
00139   }
00140   DoublePage::array hmac;
00141   copy(response.value().begin(), response.value().end(), hmac.begin());
00142   return hmac;
00143 }
00144 
00145 Result<void> DS28E16::computeSecret(int bindingDataPageNum,
00146                                     bool constantBindingData, bool anonymous,
00147                                     DoublePage::const_span partialSecret) {
00148   if (bindingDataPageNum < 0 || bindingDataPageNum >= memoryPages) {
00149     return InvalidParameterError;
00150   }
00151 
00152   uint_least8_t request[3 + DoublePage::size];
00153   request[0] = 0x3C;
00154   request[1] = bindingDataPageNum;
00155   if (constantBindingData) {
00156     request[1] |= 0x04;
00157   }
00158   if (anonymous) {
00159     request[1] |= 0xE0;
00160   }
00161   request[2] = 0x08;
00162   copy(partialSecret.begin(), partialSecret.end(), request + 3);
00163   return runCommand(request, computationTimeMs);
00164 }
00165 
00166 Result<void> DS28E16::decrementCounter() {
00167   const uint_least8_t request = 0xC9;
00168   return runCommand(make_span(&request, 1), writeMemoryTimeMs);
00169 }
00170 
00171 Result<void> DS28E16::lockOutDisableDevice() {
00172   const DisableDevicePassword::array password = {0};
00173   return disableDevice(LockOutDisableDevice, password);
00174 }
00175 
00176 Result<void>
00177 DS28E16::setDisableDevicePassword(DisableDevicePassword::const_span password) {
00178   return disableDevice(SetDisableDevicePassword, password);
00179 }
00180 
00181 Result<void>
00182 DS28E16::disableDevice(DisableDevicePassword::const_span password) {
00183   return disableDevice(DisableDevice, password);
00184 }
00185 
00186 Result<void>
00187 DS28E16::disableDevice(DisableDeviceOperation operation,
00188                        DisableDevicePassword::const_span password) {
00189   const uint_least8_t request[] = {
00190       0x33,        static_cast<uint_least8_t>(operation),
00191       password[0], password[1],
00192       0x71,        0x35,
00193       0x0E,        0xAC,
00194       0x95,        0xF8};
00195   return runCommand(request, shortWriteMemoryTimeMs);
00196 }
00197 
00198 Result<span<uint_least8_t> >
00199 DS28E16::runCommand(span<const uint_least8_t> request, int delayTime,
00200                     span<uint_least8_t> response) const {
00201   const Result<span<uint_least8_t> > responseOutput =
00202       doRunCommand(request, delayTime, response);
00203   if (!responseOutput) {
00204     return responseOutput;
00205   }
00206   if (responseOutput.value().empty()) {
00207     return InvalidResponseError;
00208   }
00209   // Parse command result byte.
00210   switch (responseOutput.value().front()) {
00211   case 0xAA:
00212     // Success response.
00213     break;
00214 
00215   case 0x00:
00216     return AuthenticationError;
00217 
00218   default:
00219     return error_code(responseOutput.value().front(), errorCategory());
00220   }
00221   if (responseOutput.value().size() != response.size()) {
00222     return InvalidResponseError;
00223   }
00224   return responseOutput.value().subspan(1);
00225 }
00226 
00227 Result<void> DS28E16::runCommand(span<const uint_least8_t> request,
00228                                  int delayTime) {
00229   uint_least8_t buffer;
00230   MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
00231   return none;
00232 }
00233 
00234 const error_category & DS28E16::errorCategory() {
00235   static class : public error_category {
00236   public:
00237     virtual const char * name() const {
00238       return "MaximInterfaceDevices.DS28E16";
00239     }
00240 
00241     virtual std::string message(int condition) const {
00242       switch (condition) {
00243       case InvalidOperationError:
00244         return "Invalid Operation Error";
00245 
00246       case InvalidParameterError:
00247         return "Invalid Parameter Error";
00248 
00249       case InvalidSequenceError:
00250         return "Invalid Sequence Error";
00251 
00252       case InternalError:
00253         return "Internal Error";
00254 
00255       case DeviceDisabledError:
00256         return "Device Disabled Error";
00257 
00258       case AuthenticationError:
00259         return "Authentication Error";
00260 
00261       case InvalidResponseError:
00262         return "Invalid Response Error";
00263       }
00264       return defaultErrorMessage(condition);
00265     }
00266   } instance;
00267   return instance;
00268 }
00269 
00270 DS28E16::PageAuthenticationData &
00271 DS28E16::PageAuthenticationData::setAnonymousRomId() {
00272   fill(romId().begin(), romId().end(), 0xFF);
00273   return *this;
00274 }
00275 
00276 DS28E16::ComputeSecretData &
00277 DS28E16::ComputeSecretData::setConstantBindingData(bool constantBindingData) {
00278   if (constantBindingData) {
00279     data.setPageNum(data.pageNum() | constantBindingDataMask);
00280     fill(bindingData().begin(), bindingData().end(), 0);
00281   } else {
00282     data.setPageNum(data.pageNum() & ~constantBindingDataMask);
00283   }
00284   return *this;
00285 }
00286 
00287 } // namespace MaximInterfaceDevices