Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.
The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface
Diff: MaximInterfaceDevices/DS28E39.cpp
- Revision:
- 8:5ea891c7d1a1
- Parent:
- 7:9cd16581b578
- Child:
- 11:3f3bf6bf5e6c
--- a/MaximInterfaceDevices/DS28E39.cpp Mon Jul 22 11:44:07 2019 -0500 +++ b/MaximInterfaceDevices/DS28E39.cpp Mon Sep 16 11:13:37 2019 -0500 @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -56,9 +56,9 @@ const int DS28E39::writePublicKeyYPage; const int DS28E39::memoryPages; -error_code DS28E39::writeMemory(int pageNum, Page::const_span page) { +Result<void> DS28E39::writeMemory(int pageNum, Page::const_span page) { if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } uint_least8_t request[2 + Page::size]; @@ -68,69 +68,71 @@ return runCommand(request, writeMemoryTimeMs); } -error_code DS28E39::readMemory(int pageNum, Page::span page) { +Result<DS28E39::Page::array> DS28E39::readMemory(int pageNum) const { if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } uint_least8_t buffer[1 + Page::size]; buffer[0] = 0x44; buffer[1] = pageNum; - span<uint_least8_t> response(buffer); - const error_code result = - runCommand(make_span(buffer, 2), readMemoryTimeMs, response); - if (!result) { - copy(response.begin(), response.end(), page.begin()); + const Result<span<uint_least8_t> > response = + runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer); + if (!response) { + return response.error(); } - return result; + Page::array page; + copy(response.value().begin(), response.value().end(), page.begin()); + return page; } -error_code DS28E39::readStatus(bool entropyHealthTest, Status & status) { +Result<DS28E39::Status> DS28E39::readStatus(bool entropyHealthTest) const { int delay = readMemoryTimeMs; if (entropyHealthTest) { delay += trngOnDemandCheckTimeMs; } - uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size + - Status::RomVersion::csize + 2]; + uint_least8_t buffer[Status::PageProtectionList::size + ManId::size + + Status::RomVersion::size + 2]; buffer[0] = 0xAA; buffer[1] = entropyHealthTest ? 0x01 : 0x00; - span<uint_least8_t> response(buffer); - error_code result = runCommand(make_span(buffer, 2), delay, response); - if (!result) { - span<uint_least8_t>::const_iterator responseIt = response.begin(); - for (Status::PageProtectionList::iterator it = - status.pageProtection.begin(); - it != status.pageProtection.end(); ++it) { - *it = *responseIt; - ++responseIt; - } - span<uint_least8_t>::const_iterator responseItEnd = - responseIt + status.manId.size(); - copy(responseIt, responseItEnd, status.manId.begin()); - responseIt = responseItEnd; - responseItEnd = responseIt + status.romVersion.size(); - copy(responseIt, responseItEnd, status.romVersion.begin()); - responseIt = responseItEnd; - switch (*responseIt) { - case Status::TestNotPerformed: - case Status::EntropyHealthy: - case Status::EntropyNotHealthy: - status.entropyHealthTestStatus = - static_cast<Status::EntropyHealthTestStatus>(*responseIt); - break; + const Result<span<uint_least8_t> > response = + runCommand(make_span(buffer, 2), delay, buffer); + if (!response) { + return response.error(); + } + Status status; + span<uint_least8_t>::const_iterator responseIt = response.value().begin(); + for (Status::PageProtectionList::array::iterator it = + status.pageProtection.begin(); + it != status.pageProtection.end(); ++it) { + *it = *responseIt; + ++responseIt; + } + span<uint_least8_t>::const_iterator responseItEnd = + responseIt + status.manId.size(); + copy(responseIt, responseItEnd, status.manId.begin()); + responseIt = responseItEnd; + responseItEnd = responseIt + status.romVersion.size(); + copy(responseIt, responseItEnd, status.romVersion.begin()); + responseIt = responseItEnd; + switch (*responseIt) { + case Status::TestNotPerformed: + case Status::EntropyHealthy: + case Status::EntropyNotHealthy: + status.entropyHealthTestStatus = + static_cast<Status::EntropyHealthTestStatus>(*responseIt); + break; - default: - result = make_error_code(InvalidResponseError); - break; - } + default: + return InvalidResponseError; } - return result; + return status; } -error_code DS28E39::setPageProtection(int pageNum, - const PageProtection & protection) { +Result<void> DS28E39::setPageProtection(int pageNum, + const PageProtection & protection) { if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } int delay = writeStateTimeMs; @@ -143,12 +145,11 @@ return runCommand(request, delay); } -error_code +Result<Ecc256::Signature::array> DS28E39::computeAndReadPageAuthentication(int pageNum, bool anonymous, - Page::const_span challenge, - Ecc256::Signature::span signature) { + Page::const_span challenge) const { if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } const size_t requestSize = 2 + Page::size; @@ -157,68 +158,71 @@ buffer[0] = 0xA5; buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00); copy(challenge.begin(), challenge.end(), buffer + 2); - span<uint_least8_t> response(buffer, responseSize); - const error_code result = runCommand(make_span(buffer, requestSize), - generateEcdsaSignatureTimeMs, response); - if (!result) { - span<uint_least8_t>::const_iterator begin = response.begin(); - span<uint_least8_t>::const_iterator end = begin + signature.s.size(); - copy(begin, end, signature.s.begin()); - begin = end; - end = begin + signature.r.size(); - copy(begin, end, signature.r.begin()); + const Result<span<uint_least8_t> > response = + runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs, + make_span(buffer, responseSize)); + if (!response) { + return response.error(); } - return result; + Ecc256::Signature::array signature; + span<uint_least8_t>::const_iterator begin = response.value().begin(); + span<uint_least8_t>::const_iterator end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + return signature; } -error_code DS28E39::decrementCounter() { +Result<void> DS28E39::decrementCounter() { const uint_least8_t request = 0xC9; return runCommand(make_span(&request, 1), writeMemoryTimeMs); } -error_code DS28E39::disableDevice() { +Result<void> DS28E39::disableDevice() { const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB, 0x10, 0x62, 0x0A, 0x26}; return runCommand(request, writeStateTimeMs); } -error_code -DS28E39::readDevicePublicKey(Ecc256::PublicKey::span devicePublicKey) { +Result<Ecc256::PublicKey::array> DS28E39::readDevicePublicKey() const { uint_least8_t buffer[1 + 2 * Ecc256::Scalar::size]; buffer[0] = 0xCB; - span<uint_least8_t> response(buffer); - const error_code result = - runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, response); - if (!result) { - span<uint_least8_t>::const_iterator begin = response.begin(); - span<uint_least8_t>::const_iterator end = begin + devicePublicKey.x.size(); - copy(begin, end, devicePublicKey.x.begin()); - begin = end; - end = begin + devicePublicKey.y.size(); - copy(begin, end, devicePublicKey.y.begin()); + const Result<span<uint_least8_t> > response = + runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, buffer); + if (!response) { + return response.error(); } - return result; + Ecc256::PublicKey::array devicePublicKey; + span<uint_least8_t>::const_iterator begin = response.value().begin(); + span<uint_least8_t>::const_iterator end = begin + devicePublicKey.x.size(); + copy(begin, end, devicePublicKey.x.begin()); + begin = end; + end = begin + devicePublicKey.y.size(); + copy(begin, end, devicePublicKey.y.begin()); + return devicePublicKey; } -error_code DS28E39::readRng(span<uint_least8_t> data) { +Result<void> DS28E39::readRng(span<uint_least8_t> data) const { const span<uint_least8_t>::index_type maxDataSize = 64; if ((data.size() < 1) || (data.size() > maxDataSize)) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } uint_least8_t buffer[1 + maxDataSize]; buffer[0] = 0xD2; buffer[1] = static_cast<uint_least8_t>(data.size() - 1); - span<uint_least8_t> response(buffer, 1 + data.size()); - const error_code result = - runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); - if (!result) { - copy(response.begin(), response.end(), data.begin()); + const Result<span<uint_least8_t> > response = + runCommand(make_span(buffer, 2), trngGenerationTimeMs, + make_span(buffer, 1 + data.size())); + if (!response) { + return response.error(); } - return result; + copy(response.value().begin(), response.value().end(), data.begin()); + return none; } -error_code +Result<void> DS28E39::authenticatePublicKey(Ecc256::Signature::const_span certificate, span<const uint_least8_t> customization) { static const span<const uint_least8_t>::index_type maxCustomizationSize = 32; @@ -226,7 +230,7 @@ 2 * Ecc256::Scalar::size; if (customization.size() < 1 || customization.size() > maxCustomizationSize) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } uint_least8_t request[1 + signatureSize + maxCustomizationSize]; @@ -238,11 +242,11 @@ return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs); } -error_code +Result<void> DS28E39::authenticatedWriteMemory(int pageNum, Page::const_span page, Ecc256::Signature::const_span signature) { if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); + return InvalidParameterError; } uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size]; @@ -255,43 +259,40 @@ return runCommand(request, verifyEcdsaSignatureTimeMs + writeMemoryTimeMs); } -error_code DS28E39::runCommand(span<const uint_least8_t> request, int delayTime, - span<uint_least8_t> & response) { - const span<const uint_least8_t>::index_type responseInputSize = - response.size(); - error_code result = doRunCommand(request, delayTime, response); - if (result) { - return result; +Result<span<uint_least8_t> > +DS28E39::runCommand(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> response) const { + const Result<span<uint_least8_t> > responseOutput = + doRunCommand(request, delayTime, response); + if (!responseOutput) { + return responseOutput; } - if (response.empty()) { - return make_error_code(InvalidResponseError); + if (responseOutput.value().empty()) { + return InvalidResponseError; } // Parse command result byte. - switch (response[0]) { + switch (responseOutput.value().front()) { case 0xAA: // Success response. - if (response.size() != responseInputSize) { - result = make_error_code(InvalidResponseError); - } break; case 0x00: - result = make_error_code(AuthenticationError); - break; + return AuthenticationError; default: - result.assign(response[0], errorCategory()); - break; + return error_code(responseOutput.value().front(), errorCategory()); } - response = response.subspan(1); - return result; + if (responseOutput.value().size() != response.size()) { + return InvalidResponseError; + } + return responseOutput.value().subspan(1); } -error_code DS28E39::runCommand(span<const uint_least8_t> request, - int delayTime) { +Result<void> DS28E39::runCommand(span<const uint_least8_t> request, + int delayTime) { uint_least8_t buffer; - span<uint_least8_t> response(&buffer, 1); - return runCommand(request, delayTime, response); + MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1))); + return none; } const error_category & DS28E39::errorCategory() { @@ -328,15 +329,6 @@ return instance; } -error_code readManId(DS28E39 & ds28e39, ManId::span manId) { - DS28E39::Status status; - const error_code result = ds28e39.readStatus(false, status); - if (!result) { - copy(make_span(status.manId), manId); - } - return result; -} - DS28E39::PageAuthenticationData & DS28E39::PageAuthenticationData::setAnonymousRomId() { std::fill(romId().begin(), romId().end(), 0xFF);