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

Committer:
IanBenzMaxim
Date:
Mon Jul 22 11:44:07 2019 -0500
Revision:
7:9cd16581b578
Child:
8:5ea891c7d1a1
Updated to version 1.9.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 7:9cd16581b578 1 /*******************************************************************************
IanBenzMaxim 7:9cd16581b578 2 * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
IanBenzMaxim 7:9cd16581b578 3 *
IanBenzMaxim 7:9cd16581b578 4 * Permission is hereby granted, free of charge, to any person obtaining a
IanBenzMaxim 7:9cd16581b578 5 * copy of this software and associated documentation files (the "Software"),
IanBenzMaxim 7:9cd16581b578 6 * to deal in the Software without restriction, including without limitation
IanBenzMaxim 7:9cd16581b578 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
IanBenzMaxim 7:9cd16581b578 8 * and/or sell copies of the Software, and to permit persons to whom the
IanBenzMaxim 7:9cd16581b578 9 * Software is furnished to do so, subject to the following conditions:
IanBenzMaxim 7:9cd16581b578 10 *
IanBenzMaxim 7:9cd16581b578 11 * The above copyright notice and this permission notice shall be included
IanBenzMaxim 7:9cd16581b578 12 * in all copies or substantial portions of the Software.
IanBenzMaxim 7:9cd16581b578 13 *
IanBenzMaxim 7:9cd16581b578 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
IanBenzMaxim 7:9cd16581b578 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
IanBenzMaxim 7:9cd16581b578 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IanBenzMaxim 7:9cd16581b578 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
IanBenzMaxim 7:9cd16581b578 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
IanBenzMaxim 7:9cd16581b578 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
IanBenzMaxim 7:9cd16581b578 20 * OTHER DEALINGS IN THE SOFTWARE.
IanBenzMaxim 7:9cd16581b578 21 *
IanBenzMaxim 7:9cd16581b578 22 * Except as contained in this notice, the name of Maxim Integrated
IanBenzMaxim 7:9cd16581b578 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
IanBenzMaxim 7:9cd16581b578 24 * Products, Inc. Branding Policy.
IanBenzMaxim 7:9cd16581b578 25 *
IanBenzMaxim 7:9cd16581b578 26 * The mere transfer of this software does not imply any licenses
IanBenzMaxim 7:9cd16581b578 27 * of trade secrets, proprietary technology, copyrights, patents,
IanBenzMaxim 7:9cd16581b578 28 * trademarks, maskwork rights, or any other form of intellectual
IanBenzMaxim 7:9cd16581b578 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
IanBenzMaxim 7:9cd16581b578 30 * ownership rights.
IanBenzMaxim 7:9cd16581b578 31 *******************************************************************************/
IanBenzMaxim 7:9cd16581b578 32
IanBenzMaxim 7:9cd16581b578 33 #include <stddef.h>
IanBenzMaxim 7:9cd16581b578 34 #include <algorithm>
IanBenzMaxim 7:9cd16581b578 35 #include <MaximInterfaceCore/Error.hpp>
IanBenzMaxim 7:9cd16581b578 36 #include "DS28E83_DS28E84.hpp"
IanBenzMaxim 7:9cd16581b578 37
IanBenzMaxim 7:9cd16581b578 38 namespace MaximInterfaceDevices {
IanBenzMaxim 7:9cd16581b578 39
IanBenzMaxim 7:9cd16581b578 40 using namespace Core;
IanBenzMaxim 7:9cd16581b578 41 using std::copy;
IanBenzMaxim 7:9cd16581b578 42
IanBenzMaxim 7:9cd16581b578 43 static const int readMemoryTimeMs = 2;
IanBenzMaxim 7:9cd16581b578 44 static const int writeMemoryTimeMs = 100;
IanBenzMaxim 7:9cd16581b578 45 static const int writeStateTimeMs = 15;
IanBenzMaxim 7:9cd16581b578 46 static const int generateEccKeyPairTimeMs = 350;
IanBenzMaxim 7:9cd16581b578 47 static const int generateEcdsaSignatureTimeMs = 80;
IanBenzMaxim 7:9cd16581b578 48 static const int computeTimeMs = 4;
IanBenzMaxim 7:9cd16581b578 49 static const int verifyEcdsaTimeMs = 160;
IanBenzMaxim 7:9cd16581b578 50 static const int trngGenerationTimeMs = 40;
IanBenzMaxim 7:9cd16581b578 51 static const int trngOnDemandCheckTimeMs = 65;
IanBenzMaxim 7:9cd16581b578 52
IanBenzMaxim 7:9cd16581b578 53 static const uint_least8_t computeAndReadPageAuthenticationCmd = 0xA5;
IanBenzMaxim 7:9cd16581b578 54 static const uint_least8_t readRngCmd = 0xD2;
IanBenzMaxim 7:9cd16581b578 55
IanBenzMaxim 7:9cd16581b578 56 static const int memoryPages =
IanBenzMaxim 7:9cd16581b578 57 MaximInterfaceCore_MAX(DS28E83::memoryPages, DS28E84::memoryPages);
IanBenzMaxim 7:9cd16581b578 58 static const int protectionBlocks = MaximInterfaceCore_MAX(
IanBenzMaxim 7:9cd16581b578 59 DS28E83::protectionBlocks, DS28E84::protectionBlocks);
IanBenzMaxim 7:9cd16581b578 60
IanBenzMaxim 7:9cd16581b578 61 const int DS28E83_DS28E84::publicKeyAxPage;
IanBenzMaxim 7:9cd16581b578 62 const int DS28E83_DS28E84::publicKeyAyPage;
IanBenzMaxim 7:9cd16581b578 63 const int DS28E83_DS28E84::publicKeyBxPage;
IanBenzMaxim 7:9cd16581b578 64 const int DS28E83_DS28E84::publicKeyByPage;
IanBenzMaxim 7:9cd16581b578 65 const int DS28E83_DS28E84::authorityPublicKeyAxPage;
IanBenzMaxim 7:9cd16581b578 66 const int DS28E83_DS28E84::authorityPublicKeyAyPage;
IanBenzMaxim 7:9cd16581b578 67 const int DS28E83_DS28E84::authorityPublicKeyBxPage;
IanBenzMaxim 7:9cd16581b578 68 const int DS28E83_DS28E84::authorityPublicKeyByPage;
IanBenzMaxim 7:9cd16581b578 69 const int DS28E83_DS28E84::privateKeyAPage;
IanBenzMaxim 7:9cd16581b578 70 const int DS28E83_DS28E84::privateKeyBPage;
IanBenzMaxim 7:9cd16581b578 71 const int DS28E83_DS28E84::secretAPage;
IanBenzMaxim 7:9cd16581b578 72 const int DS28E83_DS28E84::secretBPage;
IanBenzMaxim 7:9cd16581b578 73 const int DS28E83_DS28E84::romOptionsPage;
IanBenzMaxim 7:9cd16581b578 74 const int DS28E83_DS28E84::gpioControlPage;
IanBenzMaxim 7:9cd16581b578 75 const int DS28E83_DS28E84::publicKeySxPage;
IanBenzMaxim 7:9cd16581b578 76 const int DS28E83_DS28E84::publicKeySyPage;
IanBenzMaxim 7:9cd16581b578 77
IanBenzMaxim 7:9cd16581b578 78 const int DS28E83::memoryPages;
IanBenzMaxim 7:9cd16581b578 79 const int DS28E83::protectionBlocks;
IanBenzMaxim 7:9cd16581b578 80
IanBenzMaxim 7:9cd16581b578 81 const int DS28E84::publicKeySxBackupPage;
IanBenzMaxim 7:9cd16581b578 82 const int DS28E84::publicKeySyBackupPage;
IanBenzMaxim 7:9cd16581b578 83 const int DS28E84::decrementCounterPage;
IanBenzMaxim 7:9cd16581b578 84 const int DS28E84::memoryPages;
IanBenzMaxim 7:9cd16581b578 85 const int DS28E84::protectionBlocks;
IanBenzMaxim 7:9cd16581b578 86
IanBenzMaxim 7:9cd16581b578 87 error_code DS28E83_DS28E84::writeMemory(int pageNum, Page::const_span page) {
IanBenzMaxim 7:9cd16581b578 88 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 89 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 90 }
IanBenzMaxim 7:9cd16581b578 91
IanBenzMaxim 7:9cd16581b578 92 uint_least8_t request[2 + Page::size];
IanBenzMaxim 7:9cd16581b578 93 request[0] = 0x96;
IanBenzMaxim 7:9cd16581b578 94 request[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 95 copy(page.begin(), page.end(), request + 2);
IanBenzMaxim 7:9cd16581b578 96 return runCommand(request, writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 97 }
IanBenzMaxim 7:9cd16581b578 98
IanBenzMaxim 7:9cd16581b578 99 error_code DS28E83_DS28E84::readMemory(int pageNum, Page::span page) {
IanBenzMaxim 7:9cd16581b578 100 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 101 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 102 }
IanBenzMaxim 7:9cd16581b578 103
IanBenzMaxim 7:9cd16581b578 104 uint_least8_t buffer[1 + Page::size];
IanBenzMaxim 7:9cd16581b578 105 buffer[0] = 0x44;
IanBenzMaxim 7:9cd16581b578 106 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 107 span<uint_least8_t> response(buffer);
IanBenzMaxim 7:9cd16581b578 108 const error_code result =
IanBenzMaxim 7:9cd16581b578 109 runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
IanBenzMaxim 7:9cd16581b578 110 if (!result) {
IanBenzMaxim 7:9cd16581b578 111 copy(response.begin(), response.end(), page.begin());
IanBenzMaxim 7:9cd16581b578 112 }
IanBenzMaxim 7:9cd16581b578 113 return result;
IanBenzMaxim 7:9cd16581b578 114 }
IanBenzMaxim 7:9cd16581b578 115
IanBenzMaxim 7:9cd16581b578 116 error_code DS28E83_DS28E84::encryptedReadMemory(
IanBenzMaxim 7:9cd16581b578 117 int pageNum, KeySecret secret,
IanBenzMaxim 7:9cd16581b578 118 EncryptionChallenge::span encryptionChallenge, Page::span encryptedPage) {
IanBenzMaxim 7:9cd16581b578 119 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 120 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 121 }
IanBenzMaxim 7:9cd16581b578 122
IanBenzMaxim 7:9cd16581b578 123 const size_t requestSize = 3;
IanBenzMaxim 7:9cd16581b578 124 const size_t responseSize = 1 + EncryptionChallenge::size + Page::size;
IanBenzMaxim 7:9cd16581b578 125 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 126 buffer[0] = 0x4B;
IanBenzMaxim 7:9cd16581b578 127 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 128 buffer[2] = secret;
IanBenzMaxim 7:9cd16581b578 129 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 130 const error_code result =
IanBenzMaxim 7:9cd16581b578 131 runCommand(make_span(buffer, requestSize),
IanBenzMaxim 7:9cd16581b578 132 readMemoryTimeMs + computeTimeMs, response);
IanBenzMaxim 7:9cd16581b578 133 if (!result) {
IanBenzMaxim 7:9cd16581b578 134 span<uint_least8_t>::const_iterator begin = response.begin();
IanBenzMaxim 7:9cd16581b578 135 span<uint_least8_t>::const_iterator end =
IanBenzMaxim 7:9cd16581b578 136 begin + encryptionChallenge.size();
IanBenzMaxim 7:9cd16581b578 137 copy(begin, end, encryptionChallenge.begin());
IanBenzMaxim 7:9cd16581b578 138 begin = end;
IanBenzMaxim 7:9cd16581b578 139 end = begin + encryptedPage.size();
IanBenzMaxim 7:9cd16581b578 140 copy(begin, end, encryptedPage.begin());
IanBenzMaxim 7:9cd16581b578 141 }
IanBenzMaxim 7:9cd16581b578 142 return result;
IanBenzMaxim 7:9cd16581b578 143 }
IanBenzMaxim 7:9cd16581b578 144
IanBenzMaxim 7:9cd16581b578 145 error_code DS28E83_DS28E84::readBlockProtection(int blockNumber,
IanBenzMaxim 7:9cd16581b578 146 Optional<KeySecret> & keySecret,
IanBenzMaxim 7:9cd16581b578 147 BlockProtection & protection) {
IanBenzMaxim 7:9cd16581b578 148 if (blockNumber < 0 || blockNumber >= protectionBlocks) {
IanBenzMaxim 7:9cd16581b578 149 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 150 }
IanBenzMaxim 7:9cd16581b578 151
IanBenzMaxim 7:9cd16581b578 152 const size_t requestSize = 2;
IanBenzMaxim 7:9cd16581b578 153 const size_t responseSize = 3;
IanBenzMaxim 7:9cd16581b578 154 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 155 buffer[0] = 0xAA;
IanBenzMaxim 7:9cd16581b578 156 buffer[1] = blockNumber;
IanBenzMaxim 7:9cd16581b578 157 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 158 const error_code result =
IanBenzMaxim 7:9cd16581b578 159 runCommand(make_span(buffer, requestSize), readMemoryTimeMs, response);
IanBenzMaxim 7:9cd16581b578 160 if (result) {
IanBenzMaxim 7:9cd16581b578 161 return result;
IanBenzMaxim 7:9cd16581b578 162 }
IanBenzMaxim 7:9cd16581b578 163 if ((response[0] & 0x3F) != blockNumber) {
IanBenzMaxim 7:9cd16581b578 164 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 165 }
IanBenzMaxim 7:9cd16581b578 166 switch (response[0] >> 6) {
IanBenzMaxim 7:9cd16581b578 167 case 0:
IanBenzMaxim 7:9cd16581b578 168 keySecret = none;
IanBenzMaxim 7:9cd16581b578 169 break;
IanBenzMaxim 7:9cd16581b578 170 case 1:
IanBenzMaxim 7:9cd16581b578 171 keySecret = KeySecretA;
IanBenzMaxim 7:9cd16581b578 172 break;
IanBenzMaxim 7:9cd16581b578 173 case 2:
IanBenzMaxim 7:9cd16581b578 174 keySecret = KeySecretB;
IanBenzMaxim 7:9cd16581b578 175 break;
IanBenzMaxim 7:9cd16581b578 176 default:
IanBenzMaxim 7:9cd16581b578 177 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 178 }
IanBenzMaxim 7:9cd16581b578 179 if ((response[1] & 0x20) != 0) {
IanBenzMaxim 7:9cd16581b578 180 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 181 }
IanBenzMaxim 7:9cd16581b578 182 protection = response[1];
IanBenzMaxim 7:9cd16581b578 183 return error_code();
IanBenzMaxim 7:9cd16581b578 184 }
IanBenzMaxim 7:9cd16581b578 185
IanBenzMaxim 7:9cd16581b578 186 error_code
IanBenzMaxim 7:9cd16581b578 187 DS28E83_DS28E84::setBlockProtection(int blockNum, KeySecret keySecret,
IanBenzMaxim 7:9cd16581b578 188 const BlockProtection & protection) {
IanBenzMaxim 7:9cd16581b578 189 if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 190 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 191 }
IanBenzMaxim 7:9cd16581b578 192
IanBenzMaxim 7:9cd16581b578 193 const uint_least8_t request[] = {
IanBenzMaxim 7:9cd16581b578 194 0xC3,
IanBenzMaxim 7:9cd16581b578 195 static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) |
IanBenzMaxim 7:9cd16581b578 196 blockNum),
IanBenzMaxim 7:9cd16581b578 197 static_cast<uint_least8_t>(protection.to_ulong())};
IanBenzMaxim 7:9cd16581b578 198 return runCommand(request, writeStateTimeMs);
IanBenzMaxim 7:9cd16581b578 199 }
IanBenzMaxim 7:9cd16581b578 200
IanBenzMaxim 7:9cd16581b578 201 error_code DS28E83_DS28E84::computeAndReadPageAuthentication(
IanBenzMaxim 7:9cd16581b578 202 int pageNum, KeySecret key, Page::const_span challenge,
IanBenzMaxim 7:9cd16581b578 203 Ecc256::Signature::span signature) {
IanBenzMaxim 7:9cd16581b578 204 if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 205 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 206 }
IanBenzMaxim 7:9cd16581b578 207
IanBenzMaxim 7:9cd16581b578 208 const size_t requestSize = 3 + Page::size;
IanBenzMaxim 7:9cd16581b578 209 const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
IanBenzMaxim 7:9cd16581b578 210 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 211 buffer[0] = computeAndReadPageAuthenticationCmd;
IanBenzMaxim 7:9cd16581b578 212 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 213 buffer[2] = key + 3;
IanBenzMaxim 7:9cd16581b578 214 copy(challenge.begin(), challenge.end(), buffer + 3);
IanBenzMaxim 7:9cd16581b578 215 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 216 const error_code result = runCommand(make_span(buffer, requestSize),
IanBenzMaxim 7:9cd16581b578 217 generateEcdsaSignatureTimeMs, response);
IanBenzMaxim 7:9cd16581b578 218 if (!result) {
IanBenzMaxim 7:9cd16581b578 219 span<uint_least8_t>::const_iterator begin = response.begin();
IanBenzMaxim 7:9cd16581b578 220 span<uint_least8_t>::const_iterator end = begin + signature.s.size();
IanBenzMaxim 7:9cd16581b578 221 copy(begin, end, signature.s.begin());
IanBenzMaxim 7:9cd16581b578 222 begin = end;
IanBenzMaxim 7:9cd16581b578 223 end = begin + signature.r.size();
IanBenzMaxim 7:9cd16581b578 224 copy(begin, end, signature.r.begin());
IanBenzMaxim 7:9cd16581b578 225 }
IanBenzMaxim 7:9cd16581b578 226 return result;
IanBenzMaxim 7:9cd16581b578 227 }
IanBenzMaxim 7:9cd16581b578 228
IanBenzMaxim 7:9cd16581b578 229 error_code
IanBenzMaxim 7:9cd16581b578 230 DS28E83_DS28E84::computeAndReadPageAuthentication(int pageNum, KeySecret secret,
IanBenzMaxim 7:9cd16581b578 231 Page::const_span challenge,
IanBenzMaxim 7:9cd16581b578 232 Page::span hmac) {
IanBenzMaxim 7:9cd16581b578 233 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 234 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 235 }
IanBenzMaxim 7:9cd16581b578 236
IanBenzMaxim 7:9cd16581b578 237 const size_t requestSize = 3 + Page::size;
IanBenzMaxim 7:9cd16581b578 238 const size_t responseSize = 1 + Page::size;
IanBenzMaxim 7:9cd16581b578 239 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 240 buffer[0] = computeAndReadPageAuthenticationCmd;
IanBenzMaxim 7:9cd16581b578 241 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 242 buffer[2] = secret;
IanBenzMaxim 7:9cd16581b578 243 copy(challenge.begin(), challenge.end(), buffer + 3);
IanBenzMaxim 7:9cd16581b578 244 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 245 const error_code result =
IanBenzMaxim 7:9cd16581b578 246 runCommand(make_span(buffer, requestSize), computeTimeMs, response);
IanBenzMaxim 7:9cd16581b578 247 if (!result) {
IanBenzMaxim 7:9cd16581b578 248 copy(response.begin(), response.end(), hmac.begin());
IanBenzMaxim 7:9cd16581b578 249 }
IanBenzMaxim 7:9cd16581b578 250 return result;
IanBenzMaxim 7:9cd16581b578 251 }
IanBenzMaxim 7:9cd16581b578 252
IanBenzMaxim 7:9cd16581b578 253 error_code
IanBenzMaxim 7:9cd16581b578 254 DS28E83_DS28E84::computeMultiblockHash(bool firstBlock, bool lastBlock,
IanBenzMaxim 7:9cd16581b578 255 span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 256 const span<const uint_least8_t>::index_type maxDataSize = 64;
IanBenzMaxim 7:9cd16581b578 257
IanBenzMaxim 7:9cd16581b578 258 if (data.size() < 1 || data.size() > maxDataSize) {
IanBenzMaxim 7:9cd16581b578 259 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 260 }
IanBenzMaxim 7:9cd16581b578 261
IanBenzMaxim 7:9cd16581b578 262 uint_least8_t buffer[2 + maxDataSize];
IanBenzMaxim 7:9cd16581b578 263 buffer[0] = 0x33;
IanBenzMaxim 7:9cd16581b578 264 buffer[1] = 0;
IanBenzMaxim 7:9cd16581b578 265 if (firstBlock) {
IanBenzMaxim 7:9cd16581b578 266 buffer[1] |= 0x40;
IanBenzMaxim 7:9cd16581b578 267 }
IanBenzMaxim 7:9cd16581b578 268 if (lastBlock) {
IanBenzMaxim 7:9cd16581b578 269 buffer[1] |= 0x80;
IanBenzMaxim 7:9cd16581b578 270 }
IanBenzMaxim 7:9cd16581b578 271 copy(data.begin(), data.end(), buffer + 2);
IanBenzMaxim 7:9cd16581b578 272 return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs);
IanBenzMaxim 7:9cd16581b578 273 }
IanBenzMaxim 7:9cd16581b578 274
IanBenzMaxim 7:9cd16581b578 275 error_code DS28E83_DS28E84::verifyEcdsaSignature(
IanBenzMaxim 7:9cd16581b578 276 KeySecret key, bool authorityKey, GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 277 Ecc256::Signature::const_span signature, span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 278 return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState,
IanBenzMaxim 7:9cd16581b578 279 signature, data);
IanBenzMaxim 7:9cd16581b578 280 }
IanBenzMaxim 7:9cd16581b578 281
IanBenzMaxim 7:9cd16581b578 282 error_code DS28E83_DS28E84::verifyEcdsaSignature(
IanBenzMaxim 7:9cd16581b578 283 KeySecret key, bool authorityKey, GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 284 Ecc256::Signature::const_span signature, Page::const_span hash) {
IanBenzMaxim 7:9cd16581b578 285 return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState,
IanBenzMaxim 7:9cd16581b578 286 signature, hash);
IanBenzMaxim 7:9cd16581b578 287 }
IanBenzMaxim 7:9cd16581b578 288
IanBenzMaxim 7:9cd16581b578 289 error_code
IanBenzMaxim 7:9cd16581b578 290 DS28E83_DS28E84::verifyEcdsaSignature(KeySecret key, bool authorityKey,
IanBenzMaxim 7:9cd16581b578 291 GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 292 Ecc256::Signature::const_span signature) {
IanBenzMaxim 7:9cd16581b578 293 return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature,
IanBenzMaxim 7:9cd16581b578 294 span<const uint_least8_t>());
IanBenzMaxim 7:9cd16581b578 295 }
IanBenzMaxim 7:9cd16581b578 296
IanBenzMaxim 7:9cd16581b578 297 error_code DS28E83_DS28E84::verifyEcdsaSignature(
IanBenzMaxim 7:9cd16581b578 298 KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 299 Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) {
IanBenzMaxim 7:9cd16581b578 300 const span<const uint_least8_t>::index_type maxBufferSize = 61;
IanBenzMaxim 7:9cd16581b578 301
IanBenzMaxim 7:9cd16581b578 302 if (buffer.size() > maxBufferSize) {
IanBenzMaxim 7:9cd16581b578 303 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 304 }
IanBenzMaxim 7:9cd16581b578 305
IanBenzMaxim 7:9cd16581b578 306 uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize];
IanBenzMaxim 7:9cd16581b578 307 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 308 *requestIt++ = 0x59;
IanBenzMaxim 7:9cd16581b578 309 switch (key) {
IanBenzMaxim 7:9cd16581b578 310 case KeySecretA:
IanBenzMaxim 7:9cd16581b578 311 if (authorityKey) {
IanBenzMaxim 7:9cd16581b578 312 *requestIt = 2;
IanBenzMaxim 7:9cd16581b578 313 } else {
IanBenzMaxim 7:9cd16581b578 314 *requestIt = 0;
IanBenzMaxim 7:9cd16581b578 315 }
IanBenzMaxim 7:9cd16581b578 316 break;
IanBenzMaxim 7:9cd16581b578 317 case KeySecretB:
IanBenzMaxim 7:9cd16581b578 318 if (authorityKey) {
IanBenzMaxim 7:9cd16581b578 319 *requestIt = 3;
IanBenzMaxim 7:9cd16581b578 320 } else {
IanBenzMaxim 7:9cd16581b578 321 *requestIt = 1;
IanBenzMaxim 7:9cd16581b578 322 }
IanBenzMaxim 7:9cd16581b578 323 break;
IanBenzMaxim 7:9cd16581b578 324 case KeySecretS:
IanBenzMaxim 7:9cd16581b578 325 if (!authorityKey) {
IanBenzMaxim 7:9cd16581b578 326 *requestIt = 4;
IanBenzMaxim 7:9cd16581b578 327 break;
IanBenzMaxim 7:9cd16581b578 328 }
IanBenzMaxim 7:9cd16581b578 329 // else: Go to default case.
IanBenzMaxim 7:9cd16581b578 330 default:
IanBenzMaxim 7:9cd16581b578 331 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 332 }
IanBenzMaxim 7:9cd16581b578 333 *requestIt |= hashType << 3;
IanBenzMaxim 7:9cd16581b578 334 if (gpioState != Unchanged) {
IanBenzMaxim 7:9cd16581b578 335 *requestIt |= 0x40;
IanBenzMaxim 7:9cd16581b578 336 }
IanBenzMaxim 7:9cd16581b578 337 if (gpioState == Conducting) {
IanBenzMaxim 7:9cd16581b578 338 *requestIt |= 0x20;
IanBenzMaxim 7:9cd16581b578 339 }
IanBenzMaxim 7:9cd16581b578 340 requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt);
IanBenzMaxim 7:9cd16581b578 341 requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 342 requestIt = copy(buffer.begin(), buffer.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 343 return runCommand(make_span(request, requestIt),
IanBenzMaxim 7:9cd16581b578 344 verifyEcdsaTimeMs +
IanBenzMaxim 7:9cd16581b578 345 (hashType == DataInput ? computeTimeMs : 0));
IanBenzMaxim 7:9cd16581b578 346 }
IanBenzMaxim 7:9cd16581b578 347
IanBenzMaxim 7:9cd16581b578 348 error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
IanBenzMaxim 7:9cd16581b578 349 KeySecret key, Ecc256::Signature::const_span cert,
IanBenzMaxim 7:9cd16581b578 350 span<const uint_least8_t> certCustomization) {
IanBenzMaxim 7:9cd16581b578 351 return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL);
IanBenzMaxim 7:9cd16581b578 352 }
IanBenzMaxim 7:9cd16581b578 353
IanBenzMaxim 7:9cd16581b578 354 error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
IanBenzMaxim 7:9cd16581b578 355 KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
IanBenzMaxim 7:9cd16581b578 356 span<const uint_least8_t> certCustomization,
IanBenzMaxim 7:9cd16581b578 357 span<const uint_least8_t> ecdhCustomization) {
IanBenzMaxim 7:9cd16581b578 358 return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization,
IanBenzMaxim 7:9cd16581b578 359 &ecdhCustomization);
IanBenzMaxim 7:9cd16581b578 360 }
IanBenzMaxim 7:9cd16581b578 361
IanBenzMaxim 7:9cd16581b578 362 error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
IanBenzMaxim 7:9cd16581b578 363 KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
IanBenzMaxim 7:9cd16581b578 364 span<const uint_least8_t> certCustomization,
IanBenzMaxim 7:9cd16581b578 365 const span<const uint_least8_t> * ecdhCustomization) {
IanBenzMaxim 7:9cd16581b578 366 const span<const uint_least8_t>::index_type minCustomizationSize = 1;
IanBenzMaxim 7:9cd16581b578 367 const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32;
IanBenzMaxim 7:9cd16581b578 368 const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48;
IanBenzMaxim 7:9cd16581b578 369 const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60;
IanBenzMaxim 7:9cd16581b578 370
IanBenzMaxim 7:9cd16581b578 371 if (!(certCustomization.size() >= minCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 372 certCustomization.size() <= maxCertCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 373 (!ecdhCustomization ||
IanBenzMaxim 7:9cd16581b578 374 (ecdhCustomization->size() >= minCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 375 ecdhCustomization->size() <= maxEcdhCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 376 certCustomization.size() + ecdhCustomization->size() <=
IanBenzMaxim 7:9cd16581b578 377 maxTotalCustomizationSize)))) {
IanBenzMaxim 7:9cd16581b578 378 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 379 }
IanBenzMaxim 7:9cd16581b578 380
IanBenzMaxim 7:9cd16581b578 381 if (key == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 382 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 383 }
IanBenzMaxim 7:9cd16581b578 384
IanBenzMaxim 7:9cd16581b578 385 uint_least8_t
IanBenzMaxim 7:9cd16581b578 386 request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize];
IanBenzMaxim 7:9cd16581b578 387 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 388 *requestIt++ = 0xA8;
IanBenzMaxim 7:9cd16581b578 389 *requestIt++ = static_cast<uint_least8_t>(
IanBenzMaxim 7:9cd16581b578 390 ((certCustomization.size() - 1) << 3) | (key << 2) |
IanBenzMaxim 7:9cd16581b578 391 ((ecdhCustomization != NULL) << 1) | (authWrites << 0));
IanBenzMaxim 7:9cd16581b578 392 requestIt = copy(cert.r.begin(), cert.r.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 393 requestIt = copy(cert.s.begin(), cert.s.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 394 requestIt =
IanBenzMaxim 7:9cd16581b578 395 copy(certCustomization.begin(), certCustomization.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 396 int delay = verifyEcdsaTimeMs;
IanBenzMaxim 7:9cd16581b578 397 if (ecdhCustomization) {
IanBenzMaxim 7:9cd16581b578 398 const span<const uint_least8_t>::index_type certCustomizationPaddingSize =
IanBenzMaxim 7:9cd16581b578 399 maxCertCustomizationSize - certCustomization.size();
IanBenzMaxim 7:9cd16581b578 400 std::fill_n(requestIt, certCustomizationPaddingSize, 0);
IanBenzMaxim 7:9cd16581b578 401 requestIt += certCustomizationPaddingSize;
IanBenzMaxim 7:9cd16581b578 402 requestIt =
IanBenzMaxim 7:9cd16581b578 403 copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt);
IanBenzMaxim 7:9cd16581b578 404 delay += verifyEcdsaTimeMs;
IanBenzMaxim 7:9cd16581b578 405 }
IanBenzMaxim 7:9cd16581b578 406 return runCommand(make_span(request, requestIt), delay);
IanBenzMaxim 7:9cd16581b578 407 }
IanBenzMaxim 7:9cd16581b578 408
IanBenzMaxim 7:9cd16581b578 409 error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
IanBenzMaxim 7:9cd16581b578 410 int pageNum, bool useKeyS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 411 Ecc256::Signature::const_span signature) {
IanBenzMaxim 7:9cd16581b578 412 return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
IanBenzMaxim 7:9cd16581b578 413 NULL);
IanBenzMaxim 7:9cd16581b578 414 }
IanBenzMaxim 7:9cd16581b578 415
IanBenzMaxim 7:9cd16581b578 416 error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
IanBenzMaxim 7:9cd16581b578 417 int pageNum, bool useKeyS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 418 Ecc256::Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 419 EncryptionChallenge::const_span challenge) {
IanBenzMaxim 7:9cd16581b578 420 return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
IanBenzMaxim 7:9cd16581b578 421 &challenge);
IanBenzMaxim 7:9cd16581b578 422 }
IanBenzMaxim 7:9cd16581b578 423
IanBenzMaxim 7:9cd16581b578 424 error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
IanBenzMaxim 7:9cd16581b578 425 int pageNum, bool useKeyS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 426 Ecc256::Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 427 const EncryptionChallenge::const_span * challenge) {
IanBenzMaxim 7:9cd16581b578 428 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 429 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 430 }
IanBenzMaxim 7:9cd16581b578 431
IanBenzMaxim 7:9cd16581b578 432 uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size +
IanBenzMaxim 7:9cd16581b578 433 EncryptionChallenge::size];
IanBenzMaxim 7:9cd16581b578 434 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 435 *requestIt++ = 0x89;
IanBenzMaxim 7:9cd16581b578 436 *requestIt = pageNum;
IanBenzMaxim 7:9cd16581b578 437 if (useKeyS) {
IanBenzMaxim 7:9cd16581b578 438 *requestIt |= 0x80;
IanBenzMaxim 7:9cd16581b578 439 }
IanBenzMaxim 7:9cd16581b578 440 requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt);
IanBenzMaxim 7:9cd16581b578 441 requestIt = copy(signature.r.begin(), signature.r.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 442 requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 443 int delay = verifyEcdsaTimeMs + writeMemoryTimeMs;
IanBenzMaxim 7:9cd16581b578 444 if (challenge) {
IanBenzMaxim 7:9cd16581b578 445 requestIt = copy(challenge->begin(), challenge->end(), requestIt);
IanBenzMaxim 7:9cd16581b578 446 delay += computeTimeMs;
IanBenzMaxim 7:9cd16581b578 447 }
IanBenzMaxim 7:9cd16581b578 448 return runCommand(make_span(request, requestIt), delay);
IanBenzMaxim 7:9cd16581b578 449 }
IanBenzMaxim 7:9cd16581b578 450
IanBenzMaxim 7:9cd16581b578 451 error_code
IanBenzMaxim 7:9cd16581b578 452 DS28E83_DS28E84::authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
IanBenzMaxim 7:9cd16581b578 453 Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 454 Page::const_span hmac) {
IanBenzMaxim 7:9cd16581b578 455 return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
IanBenzMaxim 7:9cd16581b578 456 NULL);
IanBenzMaxim 7:9cd16581b578 457 }
IanBenzMaxim 7:9cd16581b578 458
IanBenzMaxim 7:9cd16581b578 459 error_code DS28E83_DS28E84::authenticatedSha256WriteMemory(
IanBenzMaxim 7:9cd16581b578 460 int pageNum, bool useSecretS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 461 Page::const_span hmac, EncryptionChallenge::const_span challenge) {
IanBenzMaxim 7:9cd16581b578 462 return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
IanBenzMaxim 7:9cd16581b578 463 &challenge);
IanBenzMaxim 7:9cd16581b578 464 }
IanBenzMaxim 7:9cd16581b578 465
IanBenzMaxim 7:9cd16581b578 466 error_code DS28E83_DS28E84::authenticatedSha256WriteMemory(
IanBenzMaxim 7:9cd16581b578 467 int pageNum, bool useSecretS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 468 Page::const_span hmac, const EncryptionChallenge::const_span * challenge) {
IanBenzMaxim 7:9cd16581b578 469 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 470 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 471 }
IanBenzMaxim 7:9cd16581b578 472
IanBenzMaxim 7:9cd16581b578 473 uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size];
IanBenzMaxim 7:9cd16581b578 474 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 475 *requestIt++ = 0x99;
IanBenzMaxim 7:9cd16581b578 476 *requestIt++ = pageNum;
IanBenzMaxim 7:9cd16581b578 477 *requestIt++ = useSecretS ? 2 : 0;
IanBenzMaxim 7:9cd16581b578 478 requestIt = copy(newPageData.begin(), newPageData.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 479 requestIt = copy(hmac.begin(), hmac.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 480 int delay = writeMemoryTimeMs + computeTimeMs;
IanBenzMaxim 7:9cd16581b578 481 if (challenge) {
IanBenzMaxim 7:9cd16581b578 482 requestIt = copy(challenge->begin(), challenge->end(), requestIt);
IanBenzMaxim 7:9cd16581b578 483 delay += computeTimeMs;
IanBenzMaxim 7:9cd16581b578 484 }
IanBenzMaxim 7:9cd16581b578 485 return runCommand(make_span(request, requestIt), delay);
IanBenzMaxim 7:9cd16581b578 486 }
IanBenzMaxim 7:9cd16581b578 487
IanBenzMaxim 7:9cd16581b578 488 error_code DS28E83_DS28E84::computeAndWriteSha256Secret(
IanBenzMaxim 7:9cd16581b578 489 int pageNum, KeySecret masterSecret, KeySecret destinationSecret,
IanBenzMaxim 7:9cd16581b578 490 Page::const_span partialSecret) {
IanBenzMaxim 7:9cd16581b578 491 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 492 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 493 }
IanBenzMaxim 7:9cd16581b578 494
IanBenzMaxim 7:9cd16581b578 495 uint_least8_t request[3 + Page::size];
IanBenzMaxim 7:9cd16581b578 496 request[0] = 0x3C;
IanBenzMaxim 7:9cd16581b578 497 request[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 498 request[2] = (destinationSecret << 2) | masterSecret;
IanBenzMaxim 7:9cd16581b578 499 copy(partialSecret.begin(), partialSecret.end(), request + 3);
IanBenzMaxim 7:9cd16581b578 500 return runCommand(request, writeMemoryTimeMs + computeTimeMs);
IanBenzMaxim 7:9cd16581b578 501 }
IanBenzMaxim 7:9cd16581b578 502
IanBenzMaxim 7:9cd16581b578 503 error_code DS28E83_DS28E84::generateEcc256KeyPair(KeySecret key) {
IanBenzMaxim 7:9cd16581b578 504 if (key == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 505 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 506 }
IanBenzMaxim 7:9cd16581b578 507
IanBenzMaxim 7:9cd16581b578 508 const uint_least8_t request[] = {0xCB, key == KeySecretB};
IanBenzMaxim 7:9cd16581b578 509 return runCommand(request, generateEccKeyPairTimeMs);
IanBenzMaxim 7:9cd16581b578 510 }
IanBenzMaxim 7:9cd16581b578 511
IanBenzMaxim 7:9cd16581b578 512 error_code DS28E83_DS28E84::readRng(span<uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 513 const span<uint_least8_t>::index_type maxDataSize = 64;
IanBenzMaxim 7:9cd16581b578 514 if ((data.size() < 1) || (data.size() > maxDataSize)) {
IanBenzMaxim 7:9cd16581b578 515 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 516 }
IanBenzMaxim 7:9cd16581b578 517
IanBenzMaxim 7:9cd16581b578 518 uint_least8_t buffer[1 + maxDataSize];
IanBenzMaxim 7:9cd16581b578 519 buffer[0] = readRngCmd;
IanBenzMaxim 7:9cd16581b578 520 buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
IanBenzMaxim 7:9cd16581b578 521 span<uint_least8_t> response(buffer, 1 + data.size());
IanBenzMaxim 7:9cd16581b578 522 const error_code result =
IanBenzMaxim 7:9cd16581b578 523 runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
IanBenzMaxim 7:9cd16581b578 524 if (!result) {
IanBenzMaxim 7:9cd16581b578 525 copy(response.begin(), response.end(), data.begin());
IanBenzMaxim 7:9cd16581b578 526 }
IanBenzMaxim 7:9cd16581b578 527 return result;
IanBenzMaxim 7:9cd16581b578 528 }
IanBenzMaxim 7:9cd16581b578 529
IanBenzMaxim 7:9cd16581b578 530 error_code DS28E83_DS28E84::entropyHealthTest() {
IanBenzMaxim 7:9cd16581b578 531 const uint_least8_t request[] = {readRngCmd, 0x80};
IanBenzMaxim 7:9cd16581b578 532 return runCommand(request, trngOnDemandCheckTimeMs);
IanBenzMaxim 7:9cd16581b578 533 }
IanBenzMaxim 7:9cd16581b578 534
IanBenzMaxim 7:9cd16581b578 535 error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request,
IanBenzMaxim 7:9cd16581b578 536 int delayTime,
IanBenzMaxim 7:9cd16581b578 537 span<uint_least8_t> & response) {
IanBenzMaxim 7:9cd16581b578 538 const span<const uint_least8_t>::index_type responseInputSize =
IanBenzMaxim 7:9cd16581b578 539 response.size();
IanBenzMaxim 7:9cd16581b578 540 error_code result = doRunCommand(request, delayTime, response);
IanBenzMaxim 7:9cd16581b578 541 if (result) {
IanBenzMaxim 7:9cd16581b578 542 return result;
IanBenzMaxim 7:9cd16581b578 543 }
IanBenzMaxim 7:9cd16581b578 544 if (response.empty()) {
IanBenzMaxim 7:9cd16581b578 545 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 546 }
IanBenzMaxim 7:9cd16581b578 547 // Parse command result byte.
IanBenzMaxim 7:9cd16581b578 548 switch (response[0]) {
IanBenzMaxim 7:9cd16581b578 549 case 0xAA:
IanBenzMaxim 7:9cd16581b578 550 // Success response.
IanBenzMaxim 7:9cd16581b578 551 if (response.size() != responseInputSize) {
IanBenzMaxim 7:9cd16581b578 552 result = make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 553 }
IanBenzMaxim 7:9cd16581b578 554 break;
IanBenzMaxim 7:9cd16581b578 555
IanBenzMaxim 7:9cd16581b578 556 case 0x00:
IanBenzMaxim 7:9cd16581b578 557 result = make_error_code(AuthenticationError);
IanBenzMaxim 7:9cd16581b578 558 break;
IanBenzMaxim 7:9cd16581b578 559
IanBenzMaxim 7:9cd16581b578 560 default:
IanBenzMaxim 7:9cd16581b578 561 result.assign(response[0], errorCategory());
IanBenzMaxim 7:9cd16581b578 562 break;
IanBenzMaxim 7:9cd16581b578 563 }
IanBenzMaxim 7:9cd16581b578 564 response = response.subspan(1);
IanBenzMaxim 7:9cd16581b578 565 return result;
IanBenzMaxim 7:9cd16581b578 566 }
IanBenzMaxim 7:9cd16581b578 567
IanBenzMaxim 7:9cd16581b578 568 error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request,
IanBenzMaxim 7:9cd16581b578 569 int delayTime) {
IanBenzMaxim 7:9cd16581b578 570 uint_least8_t buffer;
IanBenzMaxim 7:9cd16581b578 571 span<uint_least8_t> response(&buffer, 1);
IanBenzMaxim 7:9cd16581b578 572 return runCommand(request, delayTime, response);
IanBenzMaxim 7:9cd16581b578 573 }
IanBenzMaxim 7:9cd16581b578 574
IanBenzMaxim 7:9cd16581b578 575 const error_category & DS28E83_DS28E84::errorCategory() {
IanBenzMaxim 7:9cd16581b578 576 static class : public error_category {
IanBenzMaxim 7:9cd16581b578 577 public:
IanBenzMaxim 7:9cd16581b578 578 virtual const char * name() const { return "DS28E83_DS28E84"; }
IanBenzMaxim 7:9cd16581b578 579
IanBenzMaxim 7:9cd16581b578 580 virtual std::string message(int condition) const {
IanBenzMaxim 7:9cd16581b578 581 switch (condition) {
IanBenzMaxim 7:9cd16581b578 582 case InvalidOperationError:
IanBenzMaxim 7:9cd16581b578 583 return "Invalid Operation Error";
IanBenzMaxim 7:9cd16581b578 584
IanBenzMaxim 7:9cd16581b578 585 case InvalidParameterError:
IanBenzMaxim 7:9cd16581b578 586 return "Invalid Parameter Error";
IanBenzMaxim 7:9cd16581b578 587
IanBenzMaxim 7:9cd16581b578 588 case InvalidSequenceError:
IanBenzMaxim 7:9cd16581b578 589 return "Invalid Sequence Error";
IanBenzMaxim 7:9cd16581b578 590
IanBenzMaxim 7:9cd16581b578 591 case AuthenticationError:
IanBenzMaxim 7:9cd16581b578 592 return "Authentication Error";
IanBenzMaxim 7:9cd16581b578 593
IanBenzMaxim 7:9cd16581b578 594 case InternalError:
IanBenzMaxim 7:9cd16581b578 595 return "Internal Error";
IanBenzMaxim 7:9cd16581b578 596
IanBenzMaxim 7:9cd16581b578 597 case DeviceDisabledError:
IanBenzMaxim 7:9cd16581b578 598 return "Device Disabled Error";
IanBenzMaxim 7:9cd16581b578 599
IanBenzMaxim 7:9cd16581b578 600 case InvalidResponseError:
IanBenzMaxim 7:9cd16581b578 601 return "Invalid Response Error";
IanBenzMaxim 7:9cd16581b578 602 }
IanBenzMaxim 7:9cd16581b578 603 return defaultErrorMessage(condition);
IanBenzMaxim 7:9cd16581b578 604 }
IanBenzMaxim 7:9cd16581b578 605 } instance;
IanBenzMaxim 7:9cd16581b578 606 return instance;
IanBenzMaxim 7:9cd16581b578 607 }
IanBenzMaxim 7:9cd16581b578 608
IanBenzMaxim 7:9cd16581b578 609 error_code DS28E84::decrementCounter() {
IanBenzMaxim 7:9cd16581b578 610 const uint_least8_t request = 0xC9;
IanBenzMaxim 7:9cd16581b578 611 return runCommand(make_span(&request, 1), writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 612 }
IanBenzMaxim 7:9cd16581b578 613
IanBenzMaxim 7:9cd16581b578 614 error_code DS28E84::deviceStateControl(StateOperation operation) {
IanBenzMaxim 7:9cd16581b578 615 const uint_least8_t request[] = {0x55, operation == Backup};
IanBenzMaxim 7:9cd16581b578 616 return runCommand(request, writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 617 }
IanBenzMaxim 7:9cd16581b578 618
IanBenzMaxim 7:9cd16581b578 619 error_code computeMultiblockHash(DS28E83_DS28E84 & device,
IanBenzMaxim 7:9cd16581b578 620 span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 621 error_code result;
IanBenzMaxim 7:9cd16581b578 622 span<const uint_least8_t>::index_type dataIdx = 0;
IanBenzMaxim 7:9cd16581b578 623 while (dataIdx < data.size() && !result) {
IanBenzMaxim 7:9cd16581b578 624 const span<const uint_least8_t>::index_type remainingSize =
IanBenzMaxim 7:9cd16581b578 625 data.size() - dataIdx;
IanBenzMaxim 7:9cd16581b578 626 const span<const uint_least8_t>::index_type chunkSize =
IanBenzMaxim 7:9cd16581b578 627 std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
IanBenzMaxim 7:9cd16581b578 628 result =
IanBenzMaxim 7:9cd16581b578 629 device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
IanBenzMaxim 7:9cd16581b578 630 data.subspan(dataIdx, chunkSize));
IanBenzMaxim 7:9cd16581b578 631 dataIdx += chunkSize;
IanBenzMaxim 7:9cd16581b578 632 }
IanBenzMaxim 7:9cd16581b578 633 return result;
IanBenzMaxim 7:9cd16581b578 634 }
IanBenzMaxim 7:9cd16581b578 635
IanBenzMaxim 7:9cd16581b578 636 error_code readRomIdAndManId(DS28E83_DS28E84 & device, RomId::span romId,
IanBenzMaxim 7:9cd16581b578 637 ManId::span manId) {
IanBenzMaxim 7:9cd16581b578 638 DS28E83_DS28E84::Page::array page;
IanBenzMaxim 7:9cd16581b578 639 error_code result = device.readMemory(DS28E83_DS28E84::romOptionsPage, page);
IanBenzMaxim 7:9cd16581b578 640 if (!result) {
IanBenzMaxim 7:9cd16581b578 641 const DS28E83_DS28E84::RomOptions romOptions(page);
IanBenzMaxim 7:9cd16581b578 642 copy(romOptions.romId(), romId);
IanBenzMaxim 7:9cd16581b578 643 copy(romOptions.manId(), manId);
IanBenzMaxim 7:9cd16581b578 644 }
IanBenzMaxim 7:9cd16581b578 645 return result;
IanBenzMaxim 7:9cd16581b578 646 }
IanBenzMaxim 7:9cd16581b578 647
IanBenzMaxim 7:9cd16581b578 648 static void setAnonymous(RomId::span romId) {
IanBenzMaxim 7:9cd16581b578 649 std::fill(romId.begin(), romId.end(), 0xFF);
IanBenzMaxim 7:9cd16581b578 650 }
IanBenzMaxim 7:9cd16581b578 651
IanBenzMaxim 7:9cd16581b578 652 DS28E83_DS28E84::PageAuthenticationData &
IanBenzMaxim 7:9cd16581b578 653 DS28E83_DS28E84::PageAuthenticationData::setAnonymousRomId() {
IanBenzMaxim 7:9cd16581b578 654 setAnonymous(romId());
IanBenzMaxim 7:9cd16581b578 655 return *this;
IanBenzMaxim 7:9cd16581b578 656 }
IanBenzMaxim 7:9cd16581b578 657
IanBenzMaxim 7:9cd16581b578 658 DS28E83_DS28E84::ComputeSecretData::ComputeSecretData() : data() {
IanBenzMaxim 7:9cd16581b578 659 setPageNum(0);
IanBenzMaxim 7:9cd16581b578 660 setManId(ManId::array());
IanBenzMaxim 7:9cd16581b578 661 }
IanBenzMaxim 7:9cd16581b578 662
IanBenzMaxim 7:9cd16581b578 663 DS28E83_DS28E84::ComputeSecretData &
IanBenzMaxim 7:9cd16581b578 664 DS28E83_DS28E84::ComputeSecretData::setManId(ManId::const_span manId) {
IanBenzMaxim 7:9cd16581b578 665 ManId::array validatedManId;
IanBenzMaxim 7:9cd16581b578 666 copy(manId, make_span(validatedManId));
IanBenzMaxim 7:9cd16581b578 667 validatedManId[1] |= 0x80;
IanBenzMaxim 7:9cd16581b578 668 data.setManId(validatedManId);
IanBenzMaxim 7:9cd16581b578 669 return *this;
IanBenzMaxim 7:9cd16581b578 670 }
IanBenzMaxim 7:9cd16581b578 671
IanBenzMaxim 7:9cd16581b578 672 DS28E83_DS28E84::DecryptionHmacData &
IanBenzMaxim 7:9cd16581b578 673 DS28E83_DS28E84::DecryptionHmacData::setAnonymousRomId() {
IanBenzMaxim 7:9cd16581b578 674 setAnonymous(romId());
IanBenzMaxim 7:9cd16581b578 675 return *this;
IanBenzMaxim 7:9cd16581b578 676 }
IanBenzMaxim 7:9cd16581b578 677
IanBenzMaxim 7:9cd16581b578 678 } // namespace MaximInterfaceDevices