Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28C40.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 "DS28C40.hpp" 00037 00038 namespace MaximInterfaceDevices { 00039 00040 using namespace Core; 00041 using std::copy; 00042 using std::pair; 00043 00044 static const int readMemoryTimeMs = 2; 00045 static const int writeMemoryTimeMs = 150; 00046 static const int writeStateTimeMs = 15; 00047 static const int generateEccKeyPairTimeMs = 500; 00048 static const int generateEcdsaSignatureTimeMs = 50; 00049 static const int computeTimeMs = 4; 00050 static const int verifyEcdsaTimeMs = 160; 00051 static const int trngGenerationTimeMs = 50; 00052 static const int trngOnDemandCheckTimeMs = 50; 00053 00054 static const uint_least8_t computeAndReadPageAuthenticationCmd = 0xA5; 00055 static const uint_least8_t readRngCmd = 0xD2; 00056 00057 const int DS28C40::publicKeyAxPage; 00058 const int DS28C40::publicKeyAyPage; 00059 const int DS28C40::publicKeyBxPage; 00060 const int DS28C40::publicKeyByPage; 00061 const int DS28C40::authorityPublicKeyAxPage; 00062 const int DS28C40::authorityPublicKeyAyPage; 00063 const int DS28C40::authorityPublicKeyBxPage; 00064 const int DS28C40::authorityPublicKeyByPage; 00065 const int DS28C40::privateKeyAPage; 00066 const int DS28C40::privateKeyBPage; 00067 const int DS28C40::secretAPage; 00068 const int DS28C40::secretBPage; 00069 const int DS28C40::romOptionsPage; 00070 const int DS28C40::gpioControlPage; 00071 const int DS28C40::publicKeySxPage; 00072 const int DS28C40::publicKeySyPage; 00073 00074 const int DS28C40::memoryPages; 00075 const int DS28C40::protectionBlocks; 00076 00077 Result<void> DS28C40::writeMemory(int pageNum, Page::const_span page) { 00078 if (pageNum < 0 || pageNum >= memoryPages) { 00079 return InvalidParameterError; 00080 } 00081 00082 uint_least8_t request[2 + Page::size]; 00083 request[0] = 0x96; 00084 request[1] = pageNum; 00085 copy(page.begin(), page.end(), request + 2); 00086 return runCommand(request, writeMemoryTimeMs); 00087 } 00088 00089 Result<DS28C40::Page::array> DS28C40::readMemory(int pageNum) const { 00090 if (pageNum < 0 || pageNum >= memoryPages) { 00091 return InvalidParameterError; 00092 } 00093 00094 uint_least8_t buffer[1 + Page::size]; 00095 buffer[0] = 0x44; 00096 buffer[1] = pageNum; 00097 const Result<span<uint_least8_t> > response = 00098 runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer); 00099 if (!response) { 00100 return response.error(); 00101 } 00102 Page::array page; 00103 copy(response.value().begin(), response.value().end(), page.begin()); 00104 return page; 00105 } 00106 00107 Result<pair<DS28C40::EncryptionChallenge::array, DS28C40::Page::array> > 00108 DS28C40::encryptedReadMemory(int pageNum, KeySecret secret) const { 00109 if (pageNum < 0 || pageNum >= memoryPages) { 00110 return InvalidParameterError; 00111 } 00112 00113 const size_t requestSize = 3; 00114 const size_t responseSize = 1 + EncryptionChallenge::size + Page::size; 00115 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; 00116 buffer[0] = 0x4B; 00117 buffer[1] = pageNum; 00118 buffer[2] = secret; 00119 const Result<span<uint_least8_t> > response = runCommand( 00120 make_span(buffer, requestSize), readMemoryTimeMs + computeTimeMs, 00121 make_span(buffer, responseSize)); 00122 if (!response) { 00123 return response.error(); 00124 } 00125 pair<EncryptionChallenge::array, Page::array> data; 00126 span<uint_least8_t>::const_iterator begin = response.value().begin(); 00127 span<uint_least8_t>::const_iterator end = begin + data.first.size(); 00128 copy(begin, end, data.first.begin()); 00129 begin = end; 00130 end = begin + data.second.size(); 00131 copy(begin, end, data.second.begin()); 00132 return data; 00133 } 00134 00135 Result<pair<Optional<DS28C40::KeySecret>, DS28C40::BlockProtection> > 00136 DS28C40::readBlockProtection(int blockNumber) const { 00137 if (blockNumber < 0 || blockNumber >= protectionBlocks) { 00138 return InvalidParameterError; 00139 } 00140 00141 const size_t requestSize = 2; 00142 const size_t responseSize = 3; 00143 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; 00144 buffer[0] = 0xAA; 00145 buffer[1] = blockNumber; 00146 const Result<span<uint_least8_t> > response = 00147 runCommand(make_span(buffer, requestSize), readMemoryTimeMs, 00148 make_span(buffer, responseSize)); 00149 if (!response) { 00150 return response.error(); 00151 } 00152 if ((response.value()[0] & 0x3F) != blockNumber) { 00153 return InvalidResponseError; 00154 } 00155 pair<Optional<KeySecret>, BlockProtection> data; 00156 switch (response.value()[0] >> 6) { 00157 case 0: 00158 data.first = none; 00159 break; 00160 case 1: 00161 data.first = KeySecretA; 00162 break; 00163 case 2: 00164 data.first = KeySecretB; 00165 break; 00166 default: 00167 return InvalidResponseError; 00168 } 00169 if ((response.value()[1] & 0x20) != 0) { 00170 return InvalidResponseError; 00171 } 00172 data.second = response.value()[1]; 00173 return data; 00174 } 00175 00176 Result<void> DS28C40::setBlockProtection(int blockNum, KeySecret keySecret, 00177 const BlockProtection & protection) { 00178 if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) { 00179 return InvalidParameterError; 00180 } 00181 00182 const uint_least8_t request[] = { 00183 0xC3, 00184 static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) | 00185 blockNum), 00186 static_cast<uint_least8_t>(protection.to_ulong())}; 00187 return runCommand(request, writeStateTimeMs); 00188 } 00189 00190 Result<Ecc256::Signature::array> DS28C40::computeAndReadEcdsaPageAuthentication( 00191 int pageNum, KeySecret key, Page::const_span challenge) const { 00192 if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) { 00193 return InvalidParameterError; 00194 } 00195 00196 const size_t requestSize = 3 + Page::size; 00197 const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; 00198 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; 00199 buffer[0] = computeAndReadPageAuthenticationCmd; 00200 buffer[1] = pageNum; 00201 buffer[2] = key + 3; 00202 copy(challenge.begin(), challenge.end(), buffer + 3); 00203 const Result<span<uint_least8_t> > response = 00204 runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs, 00205 make_span(buffer, responseSize)); 00206 if (!response) { 00207 return response.error(); 00208 } 00209 Ecc256::Signature::array signature; 00210 span<uint_least8_t>::const_iterator begin = response.value().begin(); 00211 span<uint_least8_t>::const_iterator end = begin + signature.s.size(); 00212 copy(begin, end, signature.s.begin()); 00213 begin = end; 00214 end = begin + signature.r.size(); 00215 copy(begin, end, signature.r.begin()); 00216 return signature; 00217 } 00218 00219 Result<DS28C40::Page::array> DS28C40::computeAndReadSha256PageAuthentication( 00220 int pageNum, KeySecret secret, Page::const_span challenge) const { 00221 if (pageNum < 0 || pageNum >= memoryPages) { 00222 return InvalidParameterError; 00223 } 00224 00225 const size_t requestSize = 3 + Page::size; 00226 const size_t responseSize = 1 + Page::size; 00227 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; 00228 buffer[0] = computeAndReadPageAuthenticationCmd; 00229 buffer[1] = pageNum; 00230 buffer[2] = secret; 00231 copy(challenge.begin(), challenge.end(), buffer + 3); 00232 const Result<span<uint_least8_t> > response = 00233 runCommand(make_span(buffer, requestSize), computeTimeMs, 00234 make_span(buffer, responseSize)); 00235 if (!response) { 00236 return response.error(); 00237 } 00238 Page::array hmac; 00239 copy(response.value().begin(), response.value().end(), hmac.begin()); 00240 return hmac; 00241 } 00242 00243 Result<void> DS28C40::computeMultiblockHash(bool firstBlock, bool lastBlock, 00244 span<const uint_least8_t> data) { 00245 const span<const uint_least8_t>::index_type maxDataSize = 64; 00246 00247 if (data.size() < 1 || data.size() > maxDataSize) { 00248 return InvalidParameterError; 00249 } 00250 00251 uint_least8_t buffer[2 + maxDataSize]; 00252 buffer[0] = 0x33; 00253 buffer[1] = 0; 00254 if (firstBlock) { 00255 buffer[1] |= 0x40; 00256 } 00257 if (lastBlock) { 00258 buffer[1] |= 0x80; 00259 } 00260 copy(data.begin(), data.end(), buffer + 2); 00261 return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs); 00262 } 00263 00264 Result<void> DS28C40::verifyEcdsaSignature( 00265 KeySecret key, bool authorityKey, GpioState gpioState, 00266 Ecc256::Signature::const_span signature, span<const uint_least8_t> data) { 00267 return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState, 00268 signature, data); 00269 } 00270 00271 Result<void> DS28C40::verifyEcdsaSignature( 00272 KeySecret key, bool authorityKey, GpioState gpioState, 00273 Ecc256::Signature::const_span signature, Page::const_span hash) { 00274 return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState, 00275 signature, hash); 00276 } 00277 00278 Result<void> 00279 DS28C40::verifyEcdsaSignature(KeySecret key, bool authorityKey, 00280 GpioState gpioState, 00281 Ecc256::Signature::const_span signature) { 00282 return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature, 00283 span<const uint_least8_t>()); 00284 } 00285 00286 Result<void> DS28C40::verifyEcdsaSignature( 00287 KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState, 00288 Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) { 00289 const span<const uint_least8_t>::index_type maxBufferSize = 61; 00290 00291 if (buffer.size() > maxBufferSize) { 00292 return InvalidParameterError; 00293 } 00294 00295 uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize]; 00296 uint_least8_t * requestIt = request; 00297 *requestIt++ = 0x59; 00298 switch (key) { 00299 case KeySecretA: 00300 if (authorityKey) { 00301 *requestIt = 2; 00302 } else { 00303 *requestIt = 0; 00304 } 00305 break; 00306 case KeySecretB: 00307 if (authorityKey) { 00308 *requestIt = 3; 00309 } else { 00310 *requestIt = 1; 00311 } 00312 break; 00313 case KeySecretS: 00314 if (!authorityKey) { 00315 *requestIt = 4; 00316 break; 00317 } 00318 // else: Go to default case. 00319 default: 00320 return InvalidParameterError; 00321 } 00322 *requestIt |= hashType << 3; 00323 if (gpioState != Unchanged) { 00324 *requestIt |= 0x40; 00325 } 00326 if (gpioState == Conducting) { 00327 *requestIt |= 0x20; 00328 } 00329 requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt); 00330 requestIt = copy(signature.s.begin(), signature.s.end(), requestIt); 00331 requestIt = copy(buffer.begin(), buffer.end(), requestIt); 00332 return runCommand(make_span(request, requestIt), 00333 verifyEcdsaTimeMs + 00334 (hashType == DataInput ? computeTimeMs : 0)); 00335 } 00336 00337 Result<void> DS28C40::authenticateEcdsaPublicKey( 00338 KeySecret key, Ecc256::Signature::const_span cert, 00339 span<const uint_least8_t> certCustomization) { 00340 return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL); 00341 } 00342 00343 Result<void> DS28C40::authenticateEcdsaPublicKey( 00344 KeySecret key, bool authWrites, Ecc256::Signature::const_span cert, 00345 span<const uint_least8_t> certCustomization, 00346 span<const uint_least8_t> ecdhCustomization) { 00347 return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization, 00348 &ecdhCustomization); 00349 } 00350 00351 Result<void> DS28C40::authenticateEcdsaPublicKey( 00352 KeySecret key, bool authWrites, Ecc256::Signature::const_span cert, 00353 span<const uint_least8_t> certCustomization, 00354 const span<const uint_least8_t> * ecdhCustomization) { 00355 const span<const uint_least8_t>::index_type minCustomizationSize = 1; 00356 const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32; 00357 const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48; 00358 const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60; 00359 00360 if (!(certCustomization.size() >= minCustomizationSize && 00361 certCustomization.size() <= maxCertCustomizationSize && 00362 (!ecdhCustomization || 00363 (ecdhCustomization->size() >= minCustomizationSize && 00364 ecdhCustomization->size() <= maxEcdhCustomizationSize && 00365 certCustomization.size() + ecdhCustomization->size() <= 00366 maxTotalCustomizationSize)))) { 00367 return InvalidParameterError; 00368 } 00369 00370 if (key == KeySecretS) { 00371 return InvalidParameterError; 00372 } 00373 00374 uint_least8_t 00375 request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize]; 00376 uint_least8_t * requestIt = request; 00377 *requestIt++ = 0xA8; 00378 *requestIt++ = static_cast<uint_least8_t>( 00379 ((certCustomization.size() - 1) << 3) | (key << 2) | 00380 ((ecdhCustomization != NULL) << 1) | (authWrites << 0)); 00381 requestIt = copy(cert.r.begin(), cert.r.end(), requestIt); 00382 requestIt = copy(cert.s.begin(), cert.s.end(), requestIt); 00383 requestIt = 00384 copy(certCustomization.begin(), certCustomization.end(), requestIt); 00385 int delay = verifyEcdsaTimeMs; 00386 if (ecdhCustomization) { 00387 const span<const uint_least8_t>::index_type certCustomizationPaddingSize = 00388 maxCertCustomizationSize - certCustomization.size(); 00389 std::fill_n(requestIt, certCustomizationPaddingSize, 0); 00390 requestIt += certCustomizationPaddingSize; 00391 requestIt = 00392 copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt); 00393 delay += verifyEcdsaTimeMs; 00394 } 00395 return runCommand(make_span(request, requestIt), delay); 00396 } 00397 00398 Result<void> DS28C40::authenticatedEcdsaWriteMemory( 00399 int pageNum, bool useKeyS, Page::const_span newPageData, 00400 Ecc256::Signature::const_span signature) { 00401 return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature, 00402 NULL); 00403 } 00404 00405 Result<void> DS28C40::authenticatedEcdsaWriteMemory( 00406 int pageNum, bool useKeyS, Page::const_span newPageData, 00407 Ecc256::Signature::const_span signature, 00408 EncryptionChallenge::const_span challenge) { 00409 return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature, 00410 &challenge); 00411 } 00412 00413 Result<void> DS28C40::authenticatedEcdsaWriteMemory( 00414 int pageNum, bool useKeyS, Page::const_span newPageData, 00415 Ecc256::Signature::const_span signature, 00416 const EncryptionChallenge::const_span * challenge) { 00417 if (pageNum < 0 || pageNum >= memoryPages) { 00418 return InvalidParameterError; 00419 } 00420 00421 uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size + 00422 EncryptionChallenge::size]; 00423 uint_least8_t * requestIt = request; 00424 *requestIt++ = 0x89; 00425 *requestIt = pageNum; 00426 if (useKeyS) { 00427 *requestIt |= 0x80; 00428 } 00429 requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt); 00430 requestIt = copy(signature.r.begin(), signature.r.end(), requestIt); 00431 requestIt = copy(signature.s.begin(), signature.s.end(), requestIt); 00432 int delay = verifyEcdsaTimeMs + writeMemoryTimeMs; 00433 if (challenge) { 00434 requestIt = copy(challenge->begin(), challenge->end(), requestIt); 00435 delay += computeTimeMs; 00436 } 00437 return runCommand(make_span(request, requestIt), delay); 00438 } 00439 00440 Result<void> 00441 DS28C40::authenticatedSha256WriteMemory(int pageNum, bool useSecretS, 00442 Page::const_span newPageData, 00443 Page::const_span hmac) { 00444 return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac, 00445 NULL); 00446 } 00447 00448 Result<void> DS28C40::authenticatedSha256WriteMemory( 00449 int pageNum, bool useSecretS, Page::const_span newPageData, 00450 Page::const_span hmac, EncryptionChallenge::const_span challenge) { 00451 return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac, 00452 &challenge); 00453 } 00454 00455 Result<void> DS28C40::authenticatedSha256WriteMemory( 00456 int pageNum, bool useSecretS, Page::const_span newPageData, 00457 Page::const_span hmac, const EncryptionChallenge::const_span * challenge) { 00458 if (pageNum < 0 || pageNum >= memoryPages) { 00459 return InvalidParameterError; 00460 } 00461 00462 uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size]; 00463 uint_least8_t * requestIt = request; 00464 *requestIt++ = 0x99; 00465 *requestIt++ = pageNum; 00466 *requestIt++ = useSecretS ? 2 : 0; 00467 requestIt = copy(newPageData.begin(), newPageData.end(), requestIt); 00468 requestIt = copy(hmac.begin(), hmac.end(), requestIt); 00469 int delay = writeMemoryTimeMs + computeTimeMs; 00470 if (challenge) { 00471 requestIt = copy(challenge->begin(), challenge->end(), requestIt); 00472 delay += computeTimeMs; 00473 } 00474 return runCommand(make_span(request, requestIt), delay); 00475 } 00476 00477 Result<void> 00478 DS28C40::computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret, 00479 KeySecret destinationSecret, 00480 Page::const_span partialSecret) { 00481 if (pageNum < 0 || pageNum >= memoryPages) { 00482 return InvalidParameterError; 00483 } 00484 00485 uint_least8_t request[3 + Page::size]; 00486 request[0] = 0x3C; 00487 request[1] = pageNum; 00488 request[2] = (destinationSecret << 2) | masterSecret; 00489 copy(partialSecret.begin(), partialSecret.end(), request + 3); 00490 return runCommand(request, writeMemoryTimeMs + computeTimeMs); 00491 } 00492 00493 Result<void> DS28C40::generateEcc256KeyPair(KeySecret key) { 00494 if (key == KeySecretS) { 00495 return InvalidParameterError; 00496 } 00497 00498 const uint_least8_t request[] = {0xCB, key == KeySecretB}; 00499 return runCommand(request, generateEccKeyPairTimeMs); 00500 } 00501 00502 Result<void> DS28C40::readRng(span<uint_least8_t> data) const { 00503 const span<uint_least8_t>::index_type maxDataSize = 64; 00504 if ((data.size() < 1) || (data.size() > maxDataSize)) { 00505 return InvalidParameterError; 00506 } 00507 00508 uint_least8_t buffer[1 + maxDataSize]; 00509 buffer[0] = readRngCmd; 00510 buffer[1] = static_cast<uint_least8_t>(data.size() - 1); 00511 const Result<span<uint_least8_t> > response = 00512 runCommand(make_span(buffer, 2), trngGenerationTimeMs, 00513 make_span(buffer, 1 + data.size())); 00514 if (!response) { 00515 return response.error(); 00516 } 00517 copy(response.value().begin(), response.value().end(), data.begin()); 00518 return none; 00519 } 00520 00521 Result<void> DS28C40::entropyHealthTest() const { 00522 const uint_least8_t request[] = {readRngCmd, 0x80}; 00523 return runCommand(request, trngOnDemandCheckTimeMs); 00524 } 00525 00526 Result<span<uint_least8_t> > 00527 DS28C40::runCommand(span<const uint_least8_t> request, int delayTime, 00528 span<uint_least8_t> response) const { 00529 const Result<span<uint_least8_t> > responseOutput = 00530 doRunCommand(request, delayTime, response); 00531 if (!responseOutput) { 00532 return responseOutput; 00533 } 00534 if (responseOutput.value().empty()) { 00535 return InvalidResponseError; 00536 } 00537 // Parse command result byte. 00538 switch (responseOutput.value().front()) { 00539 case 0xAA: 00540 // Success response. 00541 break; 00542 00543 case 0x00: 00544 return AuthenticationError; 00545 00546 default: 00547 return error_code(responseOutput.value().front(), errorCategory()); 00548 } 00549 if (responseOutput.value().size() != response.size()) { 00550 return InvalidResponseError; 00551 } 00552 return responseOutput.value().subspan(1); 00553 } 00554 00555 Result<void> DS28C40::runCommand(span<const uint_least8_t> request, 00556 int delayTime) const { 00557 uint_least8_t buffer; 00558 MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1))); 00559 return none; 00560 } 00561 00562 const error_category & DS28C40::errorCategory() { 00563 static class : public error_category { 00564 public: 00565 virtual const char * name() const { 00566 return "MaximInterfaceDevices.DS28C40"; 00567 } 00568 00569 virtual std::string message(int condition) const { 00570 switch (condition) { 00571 case InvalidOperationError: 00572 return "Invalid Operation Error"; 00573 00574 case InvalidParameterError: 00575 return "Invalid Parameter Error"; 00576 00577 case InvalidSequenceError: 00578 return "Invalid Sequence Error"; 00579 00580 case AuthenticationError: 00581 return "Authentication Error"; 00582 00583 case InternalError: 00584 return "Internal Error"; 00585 00586 case DeviceDisabledError: 00587 return "Device Disabled Error"; 00588 00589 case InvalidResponseError: 00590 return "Invalid Response Error"; 00591 00592 case EntropyHealthTestError: 00593 return "Entropy Health Test Error"; 00594 } 00595 return defaultErrorMessage(condition); 00596 } 00597 } instance; 00598 return instance; 00599 } 00600 00601 Result<void> computeMultiblockHash(DS28C40 & device, 00602 span<const uint_least8_t> data) { 00603 span<const uint_least8_t>::index_type dataIdx = 0; 00604 while (dataIdx < data.size()) { 00605 const span<const uint_least8_t>::index_type remainingSize = 00606 data.size() - dataIdx; 00607 const span<const uint_least8_t>::index_type chunkSize = 00608 std::min<span<const uint_least8_t>::index_type>(remainingSize, 64); 00609 MaximInterfaceCore_TRY( 00610 device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize, 00611 data.subspan(dataIdx, chunkSize))); 00612 dataIdx += chunkSize; 00613 } 00614 return none; 00615 } 00616 00617 static void setAnonymous(RomId::span romId) { 00618 std::fill(romId.begin(), romId.end(), 0xFF); 00619 } 00620 00621 DS28C40::PageAuthenticationData & 00622 DS28C40::PageAuthenticationData::setAnonymousRomId() { 00623 setAnonymous(romId()); 00624 return *this; 00625 } 00626 00627 DS28C40::ComputeSecretData::ComputeSecretData() : data() { 00628 setPageNum(0); 00629 setManId(ManId::array()); 00630 } 00631 00632 DS28C40::ComputeSecretData & 00633 DS28C40::ComputeSecretData::setManId(ManId::const_span manId) { 00634 ManId::array validatedManId; 00635 copy(manId, make_span(validatedManId)); 00636 validatedManId[1] |= 0x80; 00637 data.setManId(validatedManId); 00638 return *this; 00639 } 00640 00641 DS28C40::DecryptionHmacData & DS28C40::DecryptionHmacData::setAnonymousRomId() { 00642 setAnonymous(romId()); 00643 return *this; 00644 } 00645 00646 } // namespace MaximInterfaceDevices
Generated on Tue Jul 12 2022 11:13:09 by 1.7.2