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