Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
DS28C36_DS2476.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 <algorithm> 00034 #include <MaximInterfaceCore/Error.hpp> 00035 #include <MaximInterfaceCore/I2CMaster.hpp> 00036 #include <MaximInterfaceCore/RomId.hpp> 00037 #include "DS28C36_DS2476.hpp" 00038 00039 #define TRY MaximInterfaceCore_TRY 00040 #define TRY_VALUE MaximInterfaceCore_TRY_VALUE 00041 00042 namespace MaximInterfaceDevices { 00043 00044 using namespace Core; 00045 using namespace Ecc256; 00046 using std::copy; 00047 00048 static Result<void> convertResultByte(uint_least8_t resultByte) { 00049 return (resultByte == 0xAA) 00050 ? makeResult(none) 00051 : error_code((resultByte == 0x00) 00052 ? static_cast<int>(DS28C36::AuthenticationError) 00053 : resultByte, 00054 DS28C36::errorCategory()); 00055 } 00056 00057 const int DS28C36::publicKeyAxPage; 00058 const int DS28C36::publicKeyAyPage; 00059 const int DS28C36::publicKeyBxPage; 00060 const int DS28C36::publicKeyByPage; 00061 const int DS28C36::publicKeyCxPage; 00062 const int DS28C36::publicKeyCyPage; 00063 const int DS28C36::privateKeyAPage; 00064 const int DS28C36::privateKeyBPage; 00065 const int DS28C36::privateKeyCPage; 00066 const int DS28C36::secretAPage; 00067 const int DS28C36::secretBPage; 00068 const int DS28C36::decrementCounterPage; 00069 const int DS28C36::romOptionsPage; 00070 const int DS28C36::gpioControlPage; 00071 const int DS28C36::publicKeySxPage; 00072 const int DS28C36::publicKeySyPage; 00073 const int DS28C36::memoryPages; 00074 00075 Result<void> DS28C36::writeMemory(int pageNum, Page::const_span page) { 00076 if (pageNum < 0 || pageNum >= memoryPages) { 00077 return InvalidParameterError; 00078 } 00079 00080 uint_least8_t buffer[1 + Page::size]; 00081 buffer[0] = pageNum; 00082 copy(page.begin(), page.end(), buffer + 1); 00083 Result<void> result = writeCommand(0x96, buffer); 00084 if (!result) { 00085 return result; 00086 } 00087 sleep(writeMemoryTimeMs); 00088 result = readFixedLengthResponse(make_span(buffer, 1)); 00089 if (!result) { 00090 return result; 00091 } 00092 result = convertResultByte(buffer[0]); 00093 return result; 00094 } 00095 00096 Result<DS28C36::Page::array> DS28C36::readMemory(int pageNum) const { 00097 if (pageNum < 0 || pageNum >= memoryPages) { 00098 return InvalidParameterError; 00099 } 00100 00101 const uint_least8_t parameter = pageNum; 00102 Result<void> result = writeCommand(0x69, make_span(¶meter, 1)); 00103 if (!result) { 00104 return result.error(); 00105 } 00106 sleep(readMemoryTimeMs); 00107 array<uint_least8_t, 1 + Page::size> response; 00108 result = readFixedLengthResponse(response); 00109 if (!result) { 00110 return result.error(); 00111 } 00112 result = convertResultByte(response[0]); 00113 if (!result) { 00114 return result.error(); 00115 } 00116 Page::array page; 00117 copy(response.begin() + 1, response.end(), page.begin()); 00118 return page; 00119 } 00120 00121 Result<void> DS28C36::writeBuffer(span<const uint_least8_t> data) { 00122 return writeCommand(0x87, data); 00123 } 00124 00125 Result<std::vector<uint_least8_t> > DS28C36::readBuffer() const { 00126 TRY(writeCommand(0x5A)); 00127 std::vector<uint_least8_t> buffer(80); 00128 span<uint_least8_t>::index_type bufferLength; 00129 TRY_VALUE(bufferLength, readVariableLengthResponse(buffer)); 00130 buffer.resize(bufferLength); 00131 return buffer; 00132 } 00133 00134 Result<DS28C36::PageProtection> DS28C36::readPageProtection(int pageNum) const { 00135 if (pageNum < 0 || pageNum >= memoryPages) { 00136 return InvalidParameterError; 00137 } 00138 00139 uint_least8_t buffer = pageNum; 00140 Result<void> result = writeCommand(0xAA, make_span(&buffer, 1)); 00141 if (!result) { 00142 return result.error(); 00143 } 00144 sleep(readMemoryTimeMs); 00145 result = readFixedLengthResponse(make_span(&buffer, 1)); 00146 if (!result) { 00147 return result.error(); 00148 } 00149 return PageProtection(buffer); 00150 } 00151 00152 Result<void> DS28C36::setPageProtection(int pageNum, 00153 const PageProtection & protection) { 00154 if (pageNum < 0 || pageNum >= memoryPages) { 00155 return InvalidParameterError; 00156 } 00157 00158 uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum), 00159 static_cast<uint_least8_t>(protection.to_ulong())}; 00160 Result<void> result = writeCommand(0xC3, buffer); 00161 if (!result) { 00162 return result; 00163 } 00164 sleep(writeMemoryTimeMs); 00165 result = readFixedLengthResponse(make_span(buffer, 1)); 00166 if (!result) { 00167 return result; 00168 } 00169 result = convertResultByte(buffer[0]); 00170 return result; 00171 } 00172 00173 Result<void> DS28C36::decrementCounter() { 00174 Result<void> result = writeCommand(0xC9); 00175 if (!result) { 00176 return result; 00177 } 00178 sleep(writeMemoryTimeMs); 00179 uint_least8_t response; 00180 result = readFixedLengthResponse(make_span(&response, 1)); 00181 if (!result) { 00182 return result; 00183 } 00184 result = convertResultByte(response); 00185 return result; 00186 } 00187 00188 Result<void> DS28C36::readRng(span<uint_least8_t> data) const { 00189 if ((data.size() < 1) || (data.size() > 64)) { 00190 return InvalidParameterError; 00191 } 00192 00193 data[0] = static_cast<uint_least8_t>(data.size() - 1); 00194 Result<void> result = writeCommand(0xD2, data.first(1)); 00195 if (!result) { 00196 return result; 00197 } 00198 sleep(sha256ComputationTimeMs); 00199 result = readFixedLengthResponse(data); 00200 return result; 00201 } 00202 00203 Result<std::pair<DS28C36::EncryptionChallenge::array, DS28C36::Page::array> > 00204 DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum) const { 00205 if (pageNum < 0 || pageNum >= memoryPages) { 00206 return InvalidParameterError; 00207 } 00208 00209 const uint_least8_t parameter = (secretNum << 6) | pageNum; 00210 Result<void> result = writeCommand(0x4B, make_span(¶meter, 1)); 00211 if (!result) { 00212 return result.error(); 00213 } 00214 sleep(readMemoryTimeMs + sha256ComputationTimeMs); 00215 uint_least8_t response[1 + EncryptionChallenge::size + Page::size]; 00216 result = readFixedLengthResponse(response); 00217 if (!result) { 00218 return result.error(); 00219 } 00220 result = convertResultByte(response[0]); 00221 if (!result) { 00222 return result.error(); 00223 } 00224 std::pair<DS28C36::EncryptionChallenge::array, DS28C36::Page::array> data; 00225 const uint_least8_t * begin = response + 1; 00226 const uint_least8_t * end = begin + data.first.size(); 00227 copy(begin, end, data.first.begin()); 00228 begin = end; 00229 end = begin + data.second.size(); 00230 copy(begin, end, data.second.begin()); 00231 return data; 00232 } 00233 00234 Result<void> 00235 DS28C36::computeAndReadPageAuthentication(int pageNum, 00236 AuthType authType) const { 00237 if (pageNum < 0 || pageNum >= memoryPages) { 00238 return InvalidParameterError; 00239 } 00240 00241 const uint_least8_t parameter = (authType << 5) | pageNum; 00242 return writeCommand(0xA5, make_span(¶meter, 1)); 00243 } 00244 00245 Result<Signature::array> 00246 DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum) const { 00247 AuthType authType; 00248 switch (keyNum) { 00249 case KeyNumA: 00250 authType = EcdsaWithKeyA; 00251 break; 00252 case KeyNumB: 00253 authType = EcdsaWithKeyB; 00254 break; 00255 case KeyNumC: 00256 authType = EcdsaWithKeyC; 00257 break; 00258 default: 00259 return InvalidParameterError; 00260 } 00261 Result<void> result = computeAndReadPageAuthentication(pageNum, authType); 00262 if (!result) { 00263 return result.error(); 00264 } 00265 sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs); 00266 uint_least8_t response[1 + 2 * Scalar::size]; 00267 result = readFixedLengthResponse(response); 00268 if (!result) { 00269 return result.error(); 00270 } 00271 result = convertResultByte(response[0]); 00272 if (!result) { 00273 return result.error(); 00274 } 00275 Signature::array signature; 00276 const uint_least8_t * begin = response + 1; 00277 const uint_least8_t * end = begin + signature.s.size(); 00278 copy(begin, end, signature.s.begin()); 00279 begin = end; 00280 end = begin + signature.r.size(); 00281 copy(begin, end, signature.r.begin()); 00282 return signature; 00283 } 00284 00285 Result<DS28C36::Page::array> 00286 DS28C36::computeAndReadPageAuthentication(int pageNum, 00287 SecretNum secretNum) const { 00288 AuthType authType; 00289 switch (secretNum) { 00290 case SecretNumA: 00291 authType = HmacWithSecretA; 00292 break; 00293 case SecretNumB: 00294 authType = HmacWithSecretB; 00295 break; 00296 case SecretNumS: 00297 authType = HmacWithSecretS; 00298 break; 00299 default: 00300 return InvalidParameterError; 00301 } 00302 Result<void> result = computeAndReadPageAuthentication(pageNum, authType); 00303 if (!result) { 00304 return result.error(); 00305 } 00306 sleep(readMemoryTimeMs + sha256ComputationTimeMs); 00307 array<uint_least8_t, 1 + Page::size> response; 00308 result = readFixedLengthResponse(response); 00309 if (!result) { 00310 return result.error(); 00311 } 00312 result = convertResultByte(response[0]); 00313 if (!result) { 00314 return result.error(); 00315 } 00316 Page::array hmac; 00317 copy(response.begin() + 1, response.end(), hmac.begin()); 00318 return hmac; 00319 } 00320 00321 Result<void> DS28C36::authenticatedSha2WriteMemory(int pageNum, 00322 SecretNum secretNum, 00323 Page::const_span page) { 00324 if (pageNum < 0 || pageNum >= memoryPages) { 00325 return InvalidParameterError; 00326 } 00327 00328 uint_least8_t buffer[1 + Page::size]; 00329 buffer[0] = (secretNum << 6) | pageNum; 00330 copy(page.begin(), page.end(), buffer + 1); 00331 Result<void> result = writeCommand(0x99, buffer); 00332 if (!result) { 00333 return result; 00334 } 00335 sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs)); 00336 result = readFixedLengthResponse(make_span(buffer, 1)); 00337 if (!result) { 00338 return result; 00339 } 00340 result = convertResultByte(buffer[0]); 00341 return result; 00342 } 00343 00344 Result<void> DS28C36::computeAndLockSha2Secret(int pageNum, 00345 SecretNum msecretNum, 00346 SecretNum dsecretNum, 00347 bool writeProtectEnable) { 00348 // User pages only 00349 if (pageNum < 0 || pageNum > 15) { 00350 return InvalidParameterError; 00351 } 00352 00353 uint_least8_t buffer[] = { 00354 static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) | 00355 pageNum), 00356 static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)}; 00357 Result<void> result = writeCommand(0x3C, buffer); 00358 if (!result) { 00359 return result; 00360 } 00361 sleep(sha256ComputationTimeMs + 00362 ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs)); 00363 result = readFixedLengthResponse(make_span(buffer, 1)); 00364 if (!result) { 00365 return result; 00366 } 00367 result = convertResultByte(buffer[0]); 00368 return result; 00369 } 00370 00371 Result<void> DS28C36::generateEcc256KeyPair(KeyNum keyNum, 00372 bool writeProtectEnable) { 00373 if (keyNum == KeyNumS) { 00374 return InvalidParameterError; 00375 } 00376 00377 uint_least8_t buffer = keyNum; 00378 if (writeProtectEnable) { 00379 buffer |= 0x80; 00380 } 00381 Result<void> result = writeCommand(0xCB, make_span(&buffer, 1)); 00382 if (!result) { 00383 return result; 00384 } 00385 sleep(generateEccKeyPairTimeMs); 00386 result = readFixedLengthResponse(make_span(&buffer, 1)); 00387 if (!result) { 00388 return result; 00389 } 00390 result = convertResultByte(buffer); 00391 return result; 00392 } 00393 00394 Result<void> DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock, 00395 span<const uint_least8_t> data) { 00396 const span<const uint_least8_t>::index_type maxDataSize = 64; 00397 00398 if (data.size() < 1 || data.size() > maxDataSize) { 00399 return InvalidParameterError; 00400 } 00401 00402 uint_least8_t buffer[1 + maxDataSize]; 00403 buffer[0] = 0; 00404 if (firstBlock) { 00405 buffer[0] |= 0x40; 00406 } 00407 if (lastBlock) { 00408 buffer[0] |= 0x80; 00409 } 00410 copy(data.begin(), data.end(), buffer + 1); 00411 Result<void> result = writeCommand(0x33, make_span(buffer, data.size() + 1)); 00412 if (!result) { 00413 return result; 00414 } 00415 sleep(sha256ComputationTimeMs); 00416 result = readFixedLengthResponse(make_span(buffer, 1)); 00417 if (!result) { 00418 return result; 00419 } 00420 result = convertResultByte(buffer[0]); 00421 return result; 00422 } 00423 00424 Result<void> DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType, 00425 Signature::const_span signature, 00426 PioState pioa, PioState piob) { 00427 uint_least8_t buffer[1 + 2 * Scalar::size]; 00428 buffer[0] = keyNum | (hashType << 2); 00429 if (pioa != Unchanged) { 00430 buffer[0] |= 0x20; 00431 } 00432 if (pioa == Conducting) { 00433 buffer[0] |= 0x10; 00434 } 00435 if (piob != Unchanged) { 00436 buffer[0] |= 0x80; 00437 } 00438 if (piob == Conducting) { 00439 buffer[0] |= 0x40; 00440 } 00441 uint_least8_t * bufferIt = 00442 copy(signature.r.begin(), signature.r.end(), buffer + 1); 00443 copy(signature.s.begin(), signature.s.end(), bufferIt); 00444 Result<void> result = writeCommand(0x59, buffer); 00445 if (!result) { 00446 return result; 00447 } 00448 sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + 00449 ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0)); 00450 result = readFixedLengthResponse(make_span(buffer, 1)); 00451 if (!result) { 00452 return result; 00453 } 00454 result = convertResultByte(buffer[0]); 00455 return result; 00456 } 00457 00458 Result<void> 00459 DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum, 00460 int csOffset, 00461 Signature::const_span signature) { 00462 if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) || 00463 (csOffset > 31)) { 00464 return InvalidParameterError; 00465 } 00466 00467 uint_least8_t buffer[1 + 2 * Scalar::size]; 00468 buffer[0] = (csOffset << 3) | (keyNum << 2); 00469 if (ecdh) { 00470 buffer[0] |= 0x02; 00471 } 00472 if (authWrites) { 00473 buffer[0] |= 0x01; 00474 } 00475 uint_least8_t * bufferIt = 00476 copy(signature.r.begin(), signature.r.end(), buffer + 1); 00477 copy(signature.s.begin(), signature.s.end(), bufferIt); 00478 Result<void> result = writeCommand(0xA8, buffer); 00479 if (!result) { 00480 return result; 00481 } 00482 sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs); 00483 result = readFixedLengthResponse(make_span(buffer, 1)); 00484 if (!result) { 00485 return result; 00486 } 00487 result = convertResultByte(buffer[0]); 00488 return result; 00489 } 00490 00491 Result<void> DS28C36::authenticatedEcdsaWriteMemory(int pageNum, 00492 Page::const_span page) { 00493 if (pageNum < 0 || pageNum >= memoryPages) { 00494 return InvalidParameterError; 00495 } 00496 00497 uint_least8_t buffer[1 + Page::size]; 00498 buffer[0] = pageNum; 00499 copy(page.begin(), page.end(), buffer + 1); 00500 Result<void> result = writeCommand(0x89, buffer); 00501 if (!result) { 00502 return result; 00503 } 00504 sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs + 00505 sha256ComputationTimeMs); 00506 result = readFixedLengthResponse(make_span(buffer, 1)); 00507 if (!result) { 00508 return result; 00509 } 00510 result = convertResultByte(buffer[0]); 00511 return result; 00512 } 00513 00514 Result<void> DS28C36::writeCommand(uint_least8_t command, 00515 span<const uint_least8_t> parameters) const { 00516 Result<void> result = master->start(address_); 00517 if (!result) { 00518 master->stop(); 00519 return result; 00520 } 00521 result = master->writeByte(command); 00522 if (!result) { 00523 master->stop(); 00524 return result; 00525 } 00526 if (!parameters.empty()) { 00527 result = master->writeByte(static_cast<uint_least8_t>(parameters.size())); 00528 if (!result) { 00529 master->stop(); 00530 return result; 00531 } 00532 result = master->writeBlock(parameters); 00533 if (!result) { 00534 master->stop(); 00535 return result; 00536 } 00537 } 00538 result = master->stop(); 00539 return result; 00540 } 00541 00542 Result<span<uint_least8_t>::index_type> 00543 DS28C36::readVariableLengthResponse(span<uint_least8_t> response) const { 00544 Result<void> result = master->start(address_ | 1); 00545 if (!result) { 00546 master->stop(); 00547 return result.error(); 00548 } 00549 uint_least8_t length; 00550 if (const Result<uint_least8_t> result = master->readByte(I2CMaster::Ack)) { 00551 length = result.value(); 00552 } else { 00553 master->stop(); 00554 return result.error(); 00555 } 00556 if (length > response.size()) { 00557 master->stop(); 00558 return InvalidResponseError; 00559 } 00560 if (length > 0) { 00561 result = master->readBlock(response.first(length), I2CMaster::Nack); 00562 if (!result) { 00563 master->stop(); 00564 return result.error(); 00565 } 00566 } 00567 result = master->stop(); 00568 if (!result) { 00569 return result.error(); 00570 } 00571 return length; 00572 } 00573 00574 Result<void> 00575 DS28C36::readFixedLengthResponse(span<uint_least8_t> response) const { 00576 span<uint_least8_t>::index_type responseLength; 00577 TRY_VALUE(responseLength, readVariableLengthResponse(response)); 00578 return (responseLength == response.size()) ? makeResult(none) 00579 : InvalidResponseError; 00580 } 00581 00582 const error_category & DS28C36::errorCategory() { 00583 static class : public error_category { 00584 public: 00585 virtual const char * name() const { 00586 return "MaximInterfaceDevices.DS28C36_DS2476"; 00587 } 00588 00589 virtual std::string message(int condition) const { 00590 switch (condition) { 00591 case ProtectionError: 00592 return "Protection Error"; 00593 00594 case InvalidParameterError: 00595 return "Invalid Parameter Error"; 00596 00597 case InvalidSequenceError: 00598 return "Invalid Sequence Error"; 00599 00600 case InvalidEcdsaInputOrResultError: 00601 return "Invalid ECDSA Input or Result Error"; 00602 00603 case AuthenticationError: 00604 return "Authentication Error"; 00605 00606 case InvalidResponseError: 00607 return "Invalid Response Error"; 00608 } 00609 return defaultErrorMessage(condition); 00610 } 00611 } instance; 00612 return instance; 00613 } 00614 00615 Result<Signature::array> DS2476::generateEcdsaSignature(KeyNum keyNum) const { 00616 if (keyNum == KeyNumS) { 00617 return InvalidParameterError; 00618 } 00619 00620 const uint_least8_t parameter = keyNum; 00621 Result<void> result = writeCommand(0x1E, make_span(¶meter, 1)); 00622 if (!result) { 00623 return result.error(); 00624 } 00625 sleep(generateEcdsaSignatureTimeMs); 00626 uint_least8_t response[1 + 2 * Scalar::size]; 00627 result = readFixedLengthResponse(response); 00628 if (!result) { 00629 return result.error(); 00630 } 00631 result = convertResultByte(response[0]); 00632 if (!result) { 00633 return result.error(); 00634 } 00635 Signature::array signature; 00636 const uint_least8_t * begin = response + 1; 00637 const uint_least8_t * end = begin + signature.s.size(); 00638 copy(begin, end, signature.s.begin()); 00639 begin = end; 00640 end = begin + signature.r.size(); 00641 copy(begin, end, signature.r.begin()); 00642 return signature; 00643 } 00644 00645 Result<void> DS2476::computeSha2UniqueSecret(SecretNum msecretNum) { 00646 uint_least8_t buffer = msecretNum << 4; 00647 Result<void> result = writeCommand(0x55, make_span(&buffer, 1)); 00648 if (!result) { 00649 return result; 00650 } 00651 sleep(sha256ComputationTimeMs); 00652 result = readFixedLengthResponse(make_span(&buffer, 1)); 00653 if (!result) { 00654 return result; 00655 } 00656 result = convertResultByte(buffer); 00657 return result; 00658 } 00659 00660 Result<DS2476::Page::array> DS2476::computeSha2Hmac() const { 00661 Result<void> result = writeCommand(0x2D); 00662 if (!result) { 00663 return result.error(); 00664 } 00665 sleep(sha256ComputationTimeMs); 00666 array<uint_least8_t, 1 + Page::size> response; 00667 result = readFixedLengthResponse(response); 00668 if (!result) { 00669 return result.error(); 00670 } 00671 result = convertResultByte(response[0]); 00672 if (!result) { 00673 return result.error(); 00674 } 00675 Page::array hmac; 00676 copy(response.begin() + 1, response.end(), hmac.begin()); 00677 return hmac; 00678 } 00679 00680 Result<void> computeMultiblockHash(DS28C36 & ds28c36, 00681 span<const uint_least8_t> data) { 00682 span<const uint_least8_t>::index_type dataIdx = 0; 00683 while (dataIdx < data.size()) { 00684 const span<const uint_least8_t>::index_type remainingSize = 00685 data.size() - dataIdx; 00686 const span<const uint_least8_t>::index_type chunkSize = 00687 std::min<span<const uint_least8_t>::index_type>(remainingSize, 64); 00688 TRY(ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize, 00689 data.subspan(dataIdx, chunkSize))); 00690 dataIdx += chunkSize; 00691 } 00692 return none; 00693 } 00694 00695 Result<void> verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey, 00696 span<const uint_least8_t> data, 00697 Signature::const_span signature, 00698 DS28C36::PioState pioa, 00699 DS28C36::PioState piob) { 00700 Result<void> result = computeMultiblockHash(ds28c36, data); 00701 if (result) { 00702 result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature, 00703 pioa, piob); 00704 } 00705 return result; 00706 } 00707 00708 Result<void> verifyEcdsaSignature(DS28C36 & ds28c36, 00709 PublicKey::const_span publicKey, 00710 span<const uint_least8_t> data, 00711 Signature::const_span signature, 00712 DS28C36::PioState pioa, 00713 DS28C36::PioState piob) { 00714 Result<void> result = 00715 ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x); 00716 if (!result) { 00717 return result; 00718 } 00719 result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y); 00720 if (!result) { 00721 return result; 00722 } 00723 result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature, 00724 pioa, piob); 00725 return result; 00726 } 00727 00728 Result<void> enableCoprocessor(DS2476 & ds2476) { 00729 DS2476::Page::array page; 00730 TRY_VALUE(page, ds2476.readMemory(DS2476::gpioControlPage)); 00731 DS2476::GpioControl gpioControl(page); 00732 if (!gpioControl.pioaConducting()) { 00733 gpioControl.setPioaConducting(true); 00734 TRY(ds2476.writeMemory(DS2476::gpioControlPage, page)); 00735 } 00736 return none; 00737 } 00738 00739 Result<void> enableRomId(DS2476 & ds2476) { 00740 DS2476::Page::array page; 00741 TRY_VALUE(page, ds2476.readMemory(DS2476::romOptionsPage)); 00742 DS2476::RomOptions romOptions(page); 00743 if (!romOptions.romBlockDisable()) { 00744 romOptions.setRomBlockDisable(true); 00745 TRY(ds2476.writeMemory(DS2476::romOptionsPage, page)); 00746 } 00747 return none; 00748 } 00749 00750 static void setAnonymous(RomId::span romId) { 00751 std::fill(romId.begin(), romId.end(), 0xFF); 00752 } 00753 00754 DS28C36::PageAuthenticationData & 00755 DS28C36::PageAuthenticationData::setAnonymousRomId() { 00756 setAnonymous(romId()); 00757 return *this; 00758 } 00759 00760 DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() { 00761 setAnonymous(romId()); 00762 return *this; 00763 } 00764 00765 } // namespace MaximInterfaceDevices
Generated on Tue Jul 12 2022 11:13:08 by 1.7.2