Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28E38.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 "DS28E38.hpp" 00037 00038 namespace MaximInterfaceDevices { 00039 00040 using namespace Core; 00041 using std::copy; 00042 00043 static const int readMemoryTimeMs = 30; 00044 static const int writeMemoryTimeMs = 65; 00045 static const int writeStateTimeMs = 15; 00046 static const int generateEccKeyPairTimeMs = 200; 00047 static const int generateEcdsaSignatureTimeMs = 130; 00048 static const int trngOnDemandCheckTimeMs = 20; 00049 static const int trngGenerationTimeMs = 10; 00050 00051 const int DS28E38::decrementCounterPage; 00052 const int DS28E38::publicKeyXPage; 00053 const int DS28E38::publicKeyYPage; 00054 const int DS28E38::privateKeyPage; 00055 const int DS28E38::memoryPages; 00056 00057 Result<void> DS28E38::writeMemory(int pageNum, Page::const_span page) { 00058 if (pageNum < 0 || pageNum >= memoryPages) { 00059 return InvalidParameterError; 00060 } 00061 00062 uint_least8_t request[2 + Page::size]; 00063 request[0] = 0x96; 00064 request[1] = pageNum; 00065 copy(page.begin(), page.end(), request + 2); 00066 return runCommand(request, writeMemoryTimeMs); 00067 } 00068 00069 Result<DS28E38::Page::array> DS28E38::readMemory(int pageNum) const { 00070 if (pageNum < 0 || pageNum >= memoryPages) { 00071 return InvalidParameterError; 00072 } 00073 00074 uint_least8_t buffer[1 + Page::size]; 00075 buffer[0] = 0x44; 00076 buffer[1] = pageNum; 00077 const Result<span<uint_least8_t> > response = 00078 runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer); 00079 if (!response) { 00080 return response.error(); 00081 } 00082 Page::array page; 00083 copy(response.value().begin(), response.value().end(), page.begin()); 00084 return page; 00085 } 00086 00087 Result<DS28E38::Status> DS28E38::readStatus(bool entropyHealthTest) const { 00088 int delay = readMemoryTimeMs; 00089 if (entropyHealthTest) { 00090 delay += trngOnDemandCheckTimeMs; 00091 } 00092 uint_least8_t buffer[Status::PageProtectionList::size + ManId::size + 00093 Status::RomVersion::size + 2]; 00094 buffer[0] = 0xAA; 00095 buffer[1] = entropyHealthTest ? 0x01 : 0x00; 00096 const Result<span<uint_least8_t> > response = 00097 runCommand(make_span(buffer, 2), delay, buffer); 00098 if (!response) { 00099 return response.error(); 00100 } 00101 Status status; 00102 span<uint_least8_t>::const_iterator responseIt = response.value().begin(); 00103 for (Status::PageProtectionList::array::iterator it = 00104 status.pageProtection.begin(); 00105 it != status.pageProtection.end(); ++it) { 00106 *it = *responseIt; 00107 ++responseIt; 00108 } 00109 span<uint_least8_t>::const_iterator responseItEnd = 00110 responseIt + status.manId.size(); 00111 copy(responseIt, responseItEnd, status.manId.begin()); 00112 responseIt = responseItEnd; 00113 responseItEnd = responseIt + status.romVersion.size(); 00114 copy(responseIt, responseItEnd, status.romVersion.begin()); 00115 responseIt = responseItEnd; 00116 switch (*responseIt) { 00117 case Status::TestNotPerformed: 00118 case Status::EntropyHealthy: 00119 case Status::EntropyNotHealthy: 00120 status.entropyHealthTestStatus = 00121 static_cast<Status::EntropyHealthTestStatus>(*responseIt); 00122 break; 00123 00124 default: 00125 return InvalidResponseError; 00126 } 00127 return status; 00128 } 00129 00130 Result<void> DS28E38::setPageProtection(int pageNum, 00131 const PageProtection & protection) { 00132 if (pageNum < 0 || pageNum >= memoryPages) { 00133 return InvalidParameterError; 00134 } 00135 00136 int delay = writeStateTimeMs; 00137 if (pageNum == decrementCounterPage) { 00138 delay += writeMemoryTimeMs; 00139 } 00140 const uint_least8_t request[] = { 00141 0xC3, static_cast<uint_least8_t>(pageNum), 00142 static_cast<uint_least8_t>(protection.to_ulong())}; 00143 return runCommand(request, delay); 00144 } 00145 00146 Result<Ecc256::Signature::array> 00147 DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous, 00148 Page::const_span challenge) const { 00149 if (pageNum < 0 || pageNum >= memoryPages) { 00150 return InvalidParameterError; 00151 } 00152 00153 const size_t requestSize = 2 + Page::size; 00154 const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; 00155 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; 00156 buffer[0] = 0xA5; 00157 buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00); 00158 copy(challenge.begin(), challenge.end(), buffer + 2); 00159 const Result<span<uint_least8_t> > response = 00160 runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs, 00161 make_span(buffer, responseSize)); 00162 if (!response) { 00163 return response.error(); 00164 } 00165 Ecc256::Signature::array signature; 00166 span<uint_least8_t>::const_iterator begin = response.value().begin(); 00167 span<uint_least8_t>::const_iterator end = begin + signature.s.size(); 00168 copy(begin, end, signature.s.begin()); 00169 begin = end; 00170 end = begin + signature.r.size(); 00171 copy(begin, end, signature.r.begin()); 00172 return signature; 00173 } 00174 00175 Result<void> DS28E38::decrementCounter() { 00176 const uint_least8_t request = 0xC9; 00177 return runCommand(make_span(&request, 1), writeMemoryTimeMs); 00178 } 00179 00180 Result<void> DS28E38::disableDevice() { 00181 const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB, 00182 0x10, 0x62, 0x0A, 0x26}; 00183 return runCommand(request, writeStateTimeMs); 00184 } 00185 00186 Result<void> DS28E38::generateEcc256KeyPair(bool privateKeyPuf, 00187 bool writeProtectEnable) { 00188 int delay = generateEccKeyPairTimeMs; 00189 if (writeProtectEnable) { 00190 delay += writeStateTimeMs; 00191 } 00192 uint_least8_t request[] = {0xCB, 0x00}; 00193 if (privateKeyPuf) { 00194 request[1] |= 0x01; 00195 } 00196 if (writeProtectEnable) { 00197 request[1] |= 0x80; 00198 } 00199 return runCommand(request, delay); 00200 } 00201 00202 Result<void> DS28E38::readRng(span<uint_least8_t> data) const { 00203 const span<uint_least8_t>::index_type maxDataSize = 64; 00204 if ((data.size() < 1) || (data.size() > maxDataSize)) { 00205 return InvalidParameterError; 00206 } 00207 00208 uint_least8_t buffer[1 + maxDataSize]; 00209 buffer[0] = 0xD2; 00210 buffer[1] = static_cast<uint_least8_t>(data.size() - 1); 00211 const Result<span<uint_least8_t> > response = 00212 runCommand(make_span(buffer, 2), trngGenerationTimeMs, 00213 make_span(buffer, 1 + data.size())); 00214 if (!response) { 00215 return response.error(); 00216 } 00217 copy(response.value().begin(), response.value().end(), data.begin()); 00218 return none; 00219 } 00220 00221 Result<span<uint_least8_t> > 00222 DS28E38::runCommand(span<const uint_least8_t> request, int delayTime, 00223 span<uint_least8_t> response) const { 00224 const Result<span<uint_least8_t> > responseOutput = 00225 doRunCommand(request, delayTime, response); 00226 if (!responseOutput) { 00227 return responseOutput; 00228 } 00229 if (responseOutput.value().empty()) { 00230 return InvalidResponseError; 00231 } 00232 // Parse command result byte. 00233 switch (responseOutput.value().front()) { 00234 case 0xAA: 00235 // Success response. 00236 break; 00237 00238 case 0x00: 00239 return InvalidResponseError; 00240 00241 default: 00242 return error_code(responseOutput.value().front(), errorCategory()); 00243 } 00244 if (responseOutput.value().size() != response.size()) { 00245 return InvalidResponseError; 00246 } 00247 return responseOutput.value().subspan(1); 00248 } 00249 00250 Result<void> DS28E38::runCommand(span<const uint_least8_t> request, 00251 int delayTime) { 00252 uint_least8_t buffer; 00253 MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1))); 00254 return none; 00255 } 00256 00257 const error_category & DS28E38::errorCategory() { 00258 static class : public error_category { 00259 public: 00260 virtual const char * name() const { 00261 return "MaximInterfaceDevices.DS28E38"; 00262 } 00263 00264 virtual std::string message(int condition) const { 00265 switch (condition) { 00266 case InvalidOperationError: 00267 return "Invalid Operation Error"; 00268 00269 case InvalidParameterError: 00270 return "Invalid Parameter Error"; 00271 00272 case InvalidSequenceError: 00273 return "Invalid Sequence Error"; 00274 00275 case InternalError: 00276 return "Internal Error"; 00277 00278 case DeviceDisabledError: 00279 return "Device Disabled Error"; 00280 00281 case InvalidResponseError: 00282 return "Invalid Response Error"; 00283 } 00284 return defaultErrorMessage(condition); 00285 } 00286 } instance; 00287 return instance; 00288 } 00289 00290 DS28E38::PageAuthenticationData & 00291 DS28E38::PageAuthenticationData::setAnonymousRomId() { 00292 std::fill(romId().begin(), romId().end(), 0xFF); 00293 return *this; 00294 } 00295 00296 } // namespace MaximInterfaceDevices
Generated on Tue Jul 12 2022 11:13:12 by 1.7.2