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) 2019 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 "DS28C40.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 = 150;
IanBenzMaxim 7:9cd16581b578 45 static const int writeStateTimeMs = 15;
IanBenzMaxim 7:9cd16581b578 46 static const int generateEccKeyPairTimeMs = 500;
IanBenzMaxim 7:9cd16581b578 47 static const int generateEcdsaSignatureTimeMs = 50;
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 = 50;
IanBenzMaxim 7:9cd16581b578 51 static const int trngOnDemandCheckTimeMs = 50;
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 const int DS28C40::publicKeyAxPage;
IanBenzMaxim 7:9cd16581b578 57 const int DS28C40::publicKeyAyPage;
IanBenzMaxim 7:9cd16581b578 58 const int DS28C40::publicKeyBxPage;
IanBenzMaxim 7:9cd16581b578 59 const int DS28C40::publicKeyByPage;
IanBenzMaxim 7:9cd16581b578 60 const int DS28C40::authorityPublicKeyAxPage;
IanBenzMaxim 7:9cd16581b578 61 const int DS28C40::authorityPublicKeyAyPage;
IanBenzMaxim 7:9cd16581b578 62 const int DS28C40::authorityPublicKeyBxPage;
IanBenzMaxim 7:9cd16581b578 63 const int DS28C40::authorityPublicKeyByPage;
IanBenzMaxim 7:9cd16581b578 64 const int DS28C40::privateKeyAPage;
IanBenzMaxim 7:9cd16581b578 65 const int DS28C40::privateKeyBPage;
IanBenzMaxim 7:9cd16581b578 66 const int DS28C40::secretAPage;
IanBenzMaxim 7:9cd16581b578 67 const int DS28C40::secretBPage;
IanBenzMaxim 7:9cd16581b578 68 const int DS28C40::romOptionsPage;
IanBenzMaxim 7:9cd16581b578 69 const int DS28C40::gpioControlPage;
IanBenzMaxim 7:9cd16581b578 70 const int DS28C40::publicKeySxPage;
IanBenzMaxim 7:9cd16581b578 71 const int DS28C40::publicKeySyPage;
IanBenzMaxim 7:9cd16581b578 72
IanBenzMaxim 7:9cd16581b578 73 const int DS28C40::memoryPages;
IanBenzMaxim 7:9cd16581b578 74 const int DS28C40::protectionBlocks;
IanBenzMaxim 7:9cd16581b578 75
IanBenzMaxim 7:9cd16581b578 76 error_code DS28C40::writeMemory(int pageNum, Page::const_span page) {
IanBenzMaxim 7:9cd16581b578 77 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 78 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 79 }
IanBenzMaxim 7:9cd16581b578 80
IanBenzMaxim 7:9cd16581b578 81 uint_least8_t request[2 + Page::size];
IanBenzMaxim 7:9cd16581b578 82 request[0] = 0x96;
IanBenzMaxim 7:9cd16581b578 83 request[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 84 copy(page.begin(), page.end(), request + 2);
IanBenzMaxim 7:9cd16581b578 85 return runCommand(request, writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 86 }
IanBenzMaxim 7:9cd16581b578 87
IanBenzMaxim 7:9cd16581b578 88 error_code DS28C40::readMemory(int pageNum, Page::span page) {
IanBenzMaxim 7:9cd16581b578 89 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 90 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 91 }
IanBenzMaxim 7:9cd16581b578 92
IanBenzMaxim 7:9cd16581b578 93 uint_least8_t buffer[1 + Page::size];
IanBenzMaxim 7:9cd16581b578 94 buffer[0] = 0x44;
IanBenzMaxim 7:9cd16581b578 95 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 96 span<uint_least8_t> response(buffer);
IanBenzMaxim 7:9cd16581b578 97 const error_code result =
IanBenzMaxim 7:9cd16581b578 98 runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
IanBenzMaxim 7:9cd16581b578 99 if (!result) {
IanBenzMaxim 7:9cd16581b578 100 copy(response.begin(), response.end(), page.begin());
IanBenzMaxim 7:9cd16581b578 101 }
IanBenzMaxim 7:9cd16581b578 102 return result;
IanBenzMaxim 7:9cd16581b578 103 }
IanBenzMaxim 7:9cd16581b578 104
IanBenzMaxim 7:9cd16581b578 105 error_code
IanBenzMaxim 7:9cd16581b578 106 DS28C40::encryptedReadMemory(int pageNum, KeySecret secret,
IanBenzMaxim 7:9cd16581b578 107 EncryptionChallenge::span encryptionChallenge,
IanBenzMaxim 7:9cd16581b578 108 Page::span encryptedPage) {
IanBenzMaxim 7:9cd16581b578 109 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 110 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 111 }
IanBenzMaxim 7:9cd16581b578 112
IanBenzMaxim 7:9cd16581b578 113 const size_t requestSize = 3;
IanBenzMaxim 7:9cd16581b578 114 const size_t responseSize = 1 + EncryptionChallenge::size + Page::size;
IanBenzMaxim 7:9cd16581b578 115 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 116 buffer[0] = 0x4B;
IanBenzMaxim 7:9cd16581b578 117 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 118 buffer[2] = secret;
IanBenzMaxim 7:9cd16581b578 119 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 120 const error_code result =
IanBenzMaxim 7:9cd16581b578 121 runCommand(make_span(buffer, requestSize),
IanBenzMaxim 7:9cd16581b578 122 readMemoryTimeMs + computeTimeMs, response);
IanBenzMaxim 7:9cd16581b578 123 if (!result) {
IanBenzMaxim 7:9cd16581b578 124 span<uint_least8_t>::const_iterator begin = response.begin();
IanBenzMaxim 7:9cd16581b578 125 span<uint_least8_t>::const_iterator end =
IanBenzMaxim 7:9cd16581b578 126 begin + encryptionChallenge.size();
IanBenzMaxim 7:9cd16581b578 127 copy(begin, end, encryptionChallenge.begin());
IanBenzMaxim 7:9cd16581b578 128 begin = end;
IanBenzMaxim 7:9cd16581b578 129 end = begin + encryptedPage.size();
IanBenzMaxim 7:9cd16581b578 130 copy(begin, end, encryptedPage.begin());
IanBenzMaxim 7:9cd16581b578 131 }
IanBenzMaxim 7:9cd16581b578 132 return result;
IanBenzMaxim 7:9cd16581b578 133 }
IanBenzMaxim 7:9cd16581b578 134
IanBenzMaxim 7:9cd16581b578 135 error_code DS28C40::readBlockProtection(int blockNumber,
IanBenzMaxim 7:9cd16581b578 136 Optional<KeySecret> & keySecret,
IanBenzMaxim 7:9cd16581b578 137 BlockProtection & protection) {
IanBenzMaxim 7:9cd16581b578 138 if (blockNumber < 0 || blockNumber >= protectionBlocks) {
IanBenzMaxim 7:9cd16581b578 139 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 140 }
IanBenzMaxim 7:9cd16581b578 141
IanBenzMaxim 7:9cd16581b578 142 const size_t requestSize = 2;
IanBenzMaxim 7:9cd16581b578 143 const size_t responseSize = 3;
IanBenzMaxim 7:9cd16581b578 144 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 145 buffer[0] = 0xAA;
IanBenzMaxim 7:9cd16581b578 146 buffer[1] = blockNumber;
IanBenzMaxim 7:9cd16581b578 147 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 148 const error_code result =
IanBenzMaxim 7:9cd16581b578 149 runCommand(make_span(buffer, requestSize), readMemoryTimeMs, response);
IanBenzMaxim 7:9cd16581b578 150 if (result) {
IanBenzMaxim 7:9cd16581b578 151 return result;
IanBenzMaxim 7:9cd16581b578 152 }
IanBenzMaxim 7:9cd16581b578 153 if ((response[0] & 0x3F) != blockNumber) {
IanBenzMaxim 7:9cd16581b578 154 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 155 }
IanBenzMaxim 7:9cd16581b578 156 switch (response[0] >> 6) {
IanBenzMaxim 7:9cd16581b578 157 case 0:
IanBenzMaxim 7:9cd16581b578 158 keySecret = none;
IanBenzMaxim 7:9cd16581b578 159 break;
IanBenzMaxim 7:9cd16581b578 160 case 1:
IanBenzMaxim 7:9cd16581b578 161 keySecret = KeySecretA;
IanBenzMaxim 7:9cd16581b578 162 break;
IanBenzMaxim 7:9cd16581b578 163 case 2:
IanBenzMaxim 7:9cd16581b578 164 keySecret = KeySecretB;
IanBenzMaxim 7:9cd16581b578 165 break;
IanBenzMaxim 7:9cd16581b578 166 default:
IanBenzMaxim 7:9cd16581b578 167 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 168 }
IanBenzMaxim 7:9cd16581b578 169 if ((response[1] & 0x20) != 0) {
IanBenzMaxim 7:9cd16581b578 170 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 171 }
IanBenzMaxim 7:9cd16581b578 172 protection = response[1];
IanBenzMaxim 7:9cd16581b578 173 return error_code();
IanBenzMaxim 7:9cd16581b578 174 }
IanBenzMaxim 7:9cd16581b578 175
IanBenzMaxim 7:9cd16581b578 176 error_code DS28C40::setBlockProtection(int blockNum, KeySecret keySecret,
IanBenzMaxim 7:9cd16581b578 177 const BlockProtection & protection) {
IanBenzMaxim 7:9cd16581b578 178 if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 179 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 180 }
IanBenzMaxim 7:9cd16581b578 181
IanBenzMaxim 7:9cd16581b578 182 const uint_least8_t request[] = {
IanBenzMaxim 7:9cd16581b578 183 0xC3,
IanBenzMaxim 7:9cd16581b578 184 static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) |
IanBenzMaxim 7:9cd16581b578 185 blockNum),
IanBenzMaxim 7:9cd16581b578 186 static_cast<uint_least8_t>(protection.to_ulong())};
IanBenzMaxim 7:9cd16581b578 187 return runCommand(request, writeStateTimeMs);
IanBenzMaxim 7:9cd16581b578 188 }
IanBenzMaxim 7:9cd16581b578 189
IanBenzMaxim 7:9cd16581b578 190 error_code
IanBenzMaxim 7:9cd16581b578 191 DS28C40::computeAndReadPageAuthentication(int pageNum, KeySecret key,
IanBenzMaxim 7:9cd16581b578 192 Page::const_span challenge,
IanBenzMaxim 7:9cd16581b578 193 Ecc256::Signature::span signature) {
IanBenzMaxim 7:9cd16581b578 194 if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 195 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 196 }
IanBenzMaxim 7:9cd16581b578 197
IanBenzMaxim 7:9cd16581b578 198 const size_t requestSize = 3 + Page::size;
IanBenzMaxim 7:9cd16581b578 199 const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
IanBenzMaxim 7:9cd16581b578 200 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 201 buffer[0] = computeAndReadPageAuthenticationCmd;
IanBenzMaxim 7:9cd16581b578 202 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 203 buffer[2] = key + 3;
IanBenzMaxim 7:9cd16581b578 204 copy(challenge.begin(), challenge.end(), buffer + 3);
IanBenzMaxim 7:9cd16581b578 205 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 206 const error_code result = runCommand(make_span(buffer, requestSize),
IanBenzMaxim 7:9cd16581b578 207 generateEcdsaSignatureTimeMs, response);
IanBenzMaxim 7:9cd16581b578 208 if (!result) {
IanBenzMaxim 7:9cd16581b578 209 span<uint_least8_t>::const_iterator begin = response.begin();
IanBenzMaxim 7:9cd16581b578 210 span<uint_least8_t>::const_iterator end = begin + signature.s.size();
IanBenzMaxim 7:9cd16581b578 211 copy(begin, end, signature.s.begin());
IanBenzMaxim 7:9cd16581b578 212 begin = end;
IanBenzMaxim 7:9cd16581b578 213 end = begin + signature.r.size();
IanBenzMaxim 7:9cd16581b578 214 copy(begin, end, signature.r.begin());
IanBenzMaxim 7:9cd16581b578 215 }
IanBenzMaxim 7:9cd16581b578 216 return result;
IanBenzMaxim 7:9cd16581b578 217 }
IanBenzMaxim 7:9cd16581b578 218
IanBenzMaxim 7:9cd16581b578 219 error_code DS28C40::computeAndReadPageAuthentication(int pageNum,
IanBenzMaxim 7:9cd16581b578 220 KeySecret secret,
IanBenzMaxim 7:9cd16581b578 221 Page::const_span challenge,
IanBenzMaxim 7:9cd16581b578 222 Page::span hmac) {
IanBenzMaxim 7:9cd16581b578 223 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 224 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 225 }
IanBenzMaxim 7:9cd16581b578 226
IanBenzMaxim 7:9cd16581b578 227 const size_t requestSize = 3 + Page::size;
IanBenzMaxim 7:9cd16581b578 228 const size_t responseSize = 1 + Page::size;
IanBenzMaxim 7:9cd16581b578 229 uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
IanBenzMaxim 7:9cd16581b578 230 buffer[0] = computeAndReadPageAuthenticationCmd;
IanBenzMaxim 7:9cd16581b578 231 buffer[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 232 buffer[2] = secret;
IanBenzMaxim 7:9cd16581b578 233 copy(challenge.begin(), challenge.end(), buffer + 3);
IanBenzMaxim 7:9cd16581b578 234 span<uint_least8_t> response(buffer, responseSize);
IanBenzMaxim 7:9cd16581b578 235 const error_code result =
IanBenzMaxim 7:9cd16581b578 236 runCommand(make_span(buffer, requestSize), computeTimeMs, response);
IanBenzMaxim 7:9cd16581b578 237 if (!result) {
IanBenzMaxim 7:9cd16581b578 238 copy(response.begin(), response.end(), hmac.begin());
IanBenzMaxim 7:9cd16581b578 239 }
IanBenzMaxim 7:9cd16581b578 240 return result;
IanBenzMaxim 7:9cd16581b578 241 }
IanBenzMaxim 7:9cd16581b578 242
IanBenzMaxim 7:9cd16581b578 243 error_code DS28C40::computeMultiblockHash(bool firstBlock, bool lastBlock,
IanBenzMaxim 7:9cd16581b578 244 span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 245 const span<const uint_least8_t>::index_type maxDataSize = 64;
IanBenzMaxim 7:9cd16581b578 246
IanBenzMaxim 7:9cd16581b578 247 if (data.size() < 1 || data.size() > maxDataSize) {
IanBenzMaxim 7:9cd16581b578 248 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 249 }
IanBenzMaxim 7:9cd16581b578 250
IanBenzMaxim 7:9cd16581b578 251 uint_least8_t buffer[2 + maxDataSize];
IanBenzMaxim 7:9cd16581b578 252 buffer[0] = 0x33;
IanBenzMaxim 7:9cd16581b578 253 buffer[1] = 0;
IanBenzMaxim 7:9cd16581b578 254 if (firstBlock) {
IanBenzMaxim 7:9cd16581b578 255 buffer[1] |= 0x40;
IanBenzMaxim 7:9cd16581b578 256 }
IanBenzMaxim 7:9cd16581b578 257 if (lastBlock) {
IanBenzMaxim 7:9cd16581b578 258 buffer[1] |= 0x80;
IanBenzMaxim 7:9cd16581b578 259 }
IanBenzMaxim 7:9cd16581b578 260 copy(data.begin(), data.end(), buffer + 2);
IanBenzMaxim 7:9cd16581b578 261 return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs);
IanBenzMaxim 7:9cd16581b578 262 }
IanBenzMaxim 7:9cd16581b578 263
IanBenzMaxim 7:9cd16581b578 264 error_code DS28C40::verifyEcdsaSignature(
IanBenzMaxim 7:9cd16581b578 265 KeySecret key, bool authorityKey, GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 266 Ecc256::Signature::const_span signature, span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 267 return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState,
IanBenzMaxim 7:9cd16581b578 268 signature, data);
IanBenzMaxim 7:9cd16581b578 269 }
IanBenzMaxim 7:9cd16581b578 270
IanBenzMaxim 7:9cd16581b578 271 error_code DS28C40::verifyEcdsaSignature(
IanBenzMaxim 7:9cd16581b578 272 KeySecret key, bool authorityKey, GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 273 Ecc256::Signature::const_span signature, Page::const_span hash) {
IanBenzMaxim 7:9cd16581b578 274 return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState,
IanBenzMaxim 7:9cd16581b578 275 signature, hash);
IanBenzMaxim 7:9cd16581b578 276 }
IanBenzMaxim 7:9cd16581b578 277
IanBenzMaxim 7:9cd16581b578 278 error_code
IanBenzMaxim 7:9cd16581b578 279 DS28C40::verifyEcdsaSignature(KeySecret key, bool authorityKey,
IanBenzMaxim 7:9cd16581b578 280 GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 281 Ecc256::Signature::const_span signature) {
IanBenzMaxim 7:9cd16581b578 282 return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature,
IanBenzMaxim 7:9cd16581b578 283 span<const uint_least8_t>());
IanBenzMaxim 7:9cd16581b578 284 }
IanBenzMaxim 7:9cd16581b578 285
IanBenzMaxim 7:9cd16581b578 286 error_code DS28C40::verifyEcdsaSignature(
IanBenzMaxim 7:9cd16581b578 287 KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState,
IanBenzMaxim 7:9cd16581b578 288 Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) {
IanBenzMaxim 7:9cd16581b578 289 const span<const uint_least8_t>::index_type maxBufferSize = 61;
IanBenzMaxim 7:9cd16581b578 290
IanBenzMaxim 7:9cd16581b578 291 if (buffer.size() > maxBufferSize) {
IanBenzMaxim 7:9cd16581b578 292 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 293 }
IanBenzMaxim 7:9cd16581b578 294
IanBenzMaxim 7:9cd16581b578 295 uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize];
IanBenzMaxim 7:9cd16581b578 296 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 297 *requestIt++ = 0x59;
IanBenzMaxim 7:9cd16581b578 298 switch (key) {
IanBenzMaxim 7:9cd16581b578 299 case KeySecretA:
IanBenzMaxim 7:9cd16581b578 300 if (authorityKey) {
IanBenzMaxim 7:9cd16581b578 301 *requestIt = 2;
IanBenzMaxim 7:9cd16581b578 302 } else {
IanBenzMaxim 7:9cd16581b578 303 *requestIt = 0;
IanBenzMaxim 7:9cd16581b578 304 }
IanBenzMaxim 7:9cd16581b578 305 break;
IanBenzMaxim 7:9cd16581b578 306 case KeySecretB:
IanBenzMaxim 7:9cd16581b578 307 if (authorityKey) {
IanBenzMaxim 7:9cd16581b578 308 *requestIt = 3;
IanBenzMaxim 7:9cd16581b578 309 } else {
IanBenzMaxim 7:9cd16581b578 310 *requestIt = 1;
IanBenzMaxim 7:9cd16581b578 311 }
IanBenzMaxim 7:9cd16581b578 312 break;
IanBenzMaxim 7:9cd16581b578 313 case KeySecretS:
IanBenzMaxim 7:9cd16581b578 314 if (!authorityKey) {
IanBenzMaxim 7:9cd16581b578 315 *requestIt = 4;
IanBenzMaxim 7:9cd16581b578 316 break;
IanBenzMaxim 7:9cd16581b578 317 }
IanBenzMaxim 7:9cd16581b578 318 // else: Go to default case.
IanBenzMaxim 7:9cd16581b578 319 default:
IanBenzMaxim 7:9cd16581b578 320 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 321 }
IanBenzMaxim 7:9cd16581b578 322 *requestIt |= hashType << 3;
IanBenzMaxim 7:9cd16581b578 323 if (gpioState != Unchanged) {
IanBenzMaxim 7:9cd16581b578 324 *requestIt |= 0x40;
IanBenzMaxim 7:9cd16581b578 325 }
IanBenzMaxim 7:9cd16581b578 326 if (gpioState == Conducting) {
IanBenzMaxim 7:9cd16581b578 327 *requestIt |= 0x20;
IanBenzMaxim 7:9cd16581b578 328 }
IanBenzMaxim 7:9cd16581b578 329 requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt);
IanBenzMaxim 7:9cd16581b578 330 requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 331 requestIt = copy(buffer.begin(), buffer.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 332 return runCommand(make_span(request, requestIt),
IanBenzMaxim 7:9cd16581b578 333 verifyEcdsaTimeMs +
IanBenzMaxim 7:9cd16581b578 334 (hashType == DataInput ? computeTimeMs : 0));
IanBenzMaxim 7:9cd16581b578 335 }
IanBenzMaxim 7:9cd16581b578 336
IanBenzMaxim 7:9cd16581b578 337 error_code DS28C40::authenticateEcdsaPublicKey(
IanBenzMaxim 7:9cd16581b578 338 KeySecret key, Ecc256::Signature::const_span cert,
IanBenzMaxim 7:9cd16581b578 339 span<const uint_least8_t> certCustomization) {
IanBenzMaxim 7:9cd16581b578 340 return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL);
IanBenzMaxim 7:9cd16581b578 341 }
IanBenzMaxim 7:9cd16581b578 342
IanBenzMaxim 7:9cd16581b578 343 error_code DS28C40::authenticateEcdsaPublicKey(
IanBenzMaxim 7:9cd16581b578 344 KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
IanBenzMaxim 7:9cd16581b578 345 span<const uint_least8_t> certCustomization,
IanBenzMaxim 7:9cd16581b578 346 span<const uint_least8_t> ecdhCustomization) {
IanBenzMaxim 7:9cd16581b578 347 return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization,
IanBenzMaxim 7:9cd16581b578 348 &ecdhCustomization);
IanBenzMaxim 7:9cd16581b578 349 }
IanBenzMaxim 7:9cd16581b578 350
IanBenzMaxim 7:9cd16581b578 351 error_code DS28C40::authenticateEcdsaPublicKey(
IanBenzMaxim 7:9cd16581b578 352 KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
IanBenzMaxim 7:9cd16581b578 353 span<const uint_least8_t> certCustomization,
IanBenzMaxim 7:9cd16581b578 354 const span<const uint_least8_t> * ecdhCustomization) {
IanBenzMaxim 7:9cd16581b578 355 const span<const uint_least8_t>::index_type minCustomizationSize = 1;
IanBenzMaxim 7:9cd16581b578 356 const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32;
IanBenzMaxim 7:9cd16581b578 357 const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48;
IanBenzMaxim 7:9cd16581b578 358 const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60;
IanBenzMaxim 7:9cd16581b578 359
IanBenzMaxim 7:9cd16581b578 360 if (!(certCustomization.size() >= minCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 361 certCustomization.size() <= maxCertCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 362 (!ecdhCustomization ||
IanBenzMaxim 7:9cd16581b578 363 (ecdhCustomization->size() >= minCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 364 ecdhCustomization->size() <= maxEcdhCustomizationSize &&
IanBenzMaxim 7:9cd16581b578 365 certCustomization.size() + ecdhCustomization->size() <=
IanBenzMaxim 7:9cd16581b578 366 maxTotalCustomizationSize)))) {
IanBenzMaxim 7:9cd16581b578 367 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 368 }
IanBenzMaxim 7:9cd16581b578 369
IanBenzMaxim 7:9cd16581b578 370 if (key == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 371 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 372 }
IanBenzMaxim 7:9cd16581b578 373
IanBenzMaxim 7:9cd16581b578 374 uint_least8_t
IanBenzMaxim 7:9cd16581b578 375 request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize];
IanBenzMaxim 7:9cd16581b578 376 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 377 *requestIt++ = 0xA8;
IanBenzMaxim 7:9cd16581b578 378 *requestIt++ = static_cast<uint_least8_t>(
IanBenzMaxim 7:9cd16581b578 379 ((certCustomization.size() - 1) << 3) | (key << 2) |
IanBenzMaxim 7:9cd16581b578 380 ((ecdhCustomization != NULL) << 1) | (authWrites << 0));
IanBenzMaxim 7:9cd16581b578 381 requestIt = copy(cert.r.begin(), cert.r.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 382 requestIt = copy(cert.s.begin(), cert.s.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 383 requestIt =
IanBenzMaxim 7:9cd16581b578 384 copy(certCustomization.begin(), certCustomization.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 385 int delay = verifyEcdsaTimeMs;
IanBenzMaxim 7:9cd16581b578 386 if (ecdhCustomization) {
IanBenzMaxim 7:9cd16581b578 387 const span<const uint_least8_t>::index_type certCustomizationPaddingSize =
IanBenzMaxim 7:9cd16581b578 388 maxCertCustomizationSize - certCustomization.size();
IanBenzMaxim 7:9cd16581b578 389 std::fill_n(requestIt, certCustomizationPaddingSize, 0);
IanBenzMaxim 7:9cd16581b578 390 requestIt += certCustomizationPaddingSize;
IanBenzMaxim 7:9cd16581b578 391 requestIt =
IanBenzMaxim 7:9cd16581b578 392 copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt);
IanBenzMaxim 7:9cd16581b578 393 delay += verifyEcdsaTimeMs;
IanBenzMaxim 7:9cd16581b578 394 }
IanBenzMaxim 7:9cd16581b578 395 return runCommand(make_span(request, requestIt), delay);
IanBenzMaxim 7:9cd16581b578 396 }
IanBenzMaxim 7:9cd16581b578 397
IanBenzMaxim 7:9cd16581b578 398 error_code DS28C40::authenticatedEcdsaWriteMemory(
IanBenzMaxim 7:9cd16581b578 399 int pageNum, bool useKeyS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 400 Ecc256::Signature::const_span signature) {
IanBenzMaxim 7:9cd16581b578 401 return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
IanBenzMaxim 7:9cd16581b578 402 NULL);
IanBenzMaxim 7:9cd16581b578 403 }
IanBenzMaxim 7:9cd16581b578 404
IanBenzMaxim 7:9cd16581b578 405 error_code DS28C40::authenticatedEcdsaWriteMemory(
IanBenzMaxim 7:9cd16581b578 406 int pageNum, bool useKeyS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 407 Ecc256::Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 408 EncryptionChallenge::const_span challenge) {
IanBenzMaxim 7:9cd16581b578 409 return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
IanBenzMaxim 7:9cd16581b578 410 &challenge);
IanBenzMaxim 7:9cd16581b578 411 }
IanBenzMaxim 7:9cd16581b578 412
IanBenzMaxim 7:9cd16581b578 413 error_code DS28C40::authenticatedEcdsaWriteMemory(
IanBenzMaxim 7:9cd16581b578 414 int pageNum, bool useKeyS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 415 Ecc256::Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 416 const EncryptionChallenge::const_span * challenge) {
IanBenzMaxim 7:9cd16581b578 417 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 418 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 419 }
IanBenzMaxim 7:9cd16581b578 420
IanBenzMaxim 7:9cd16581b578 421 uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size +
IanBenzMaxim 7:9cd16581b578 422 EncryptionChallenge::size];
IanBenzMaxim 7:9cd16581b578 423 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 424 *requestIt++ = 0x89;
IanBenzMaxim 7:9cd16581b578 425 *requestIt = pageNum;
IanBenzMaxim 7:9cd16581b578 426 if (useKeyS) {
IanBenzMaxim 7:9cd16581b578 427 *requestIt |= 0x80;
IanBenzMaxim 7:9cd16581b578 428 }
IanBenzMaxim 7:9cd16581b578 429 requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt);
IanBenzMaxim 7:9cd16581b578 430 requestIt = copy(signature.r.begin(), signature.r.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 431 requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 432 int delay = verifyEcdsaTimeMs + writeMemoryTimeMs;
IanBenzMaxim 7:9cd16581b578 433 if (challenge) {
IanBenzMaxim 7:9cd16581b578 434 requestIt = copy(challenge->begin(), challenge->end(), requestIt);
IanBenzMaxim 7:9cd16581b578 435 delay += computeTimeMs;
IanBenzMaxim 7:9cd16581b578 436 }
IanBenzMaxim 7:9cd16581b578 437 return runCommand(make_span(request, requestIt), delay);
IanBenzMaxim 7:9cd16581b578 438 }
IanBenzMaxim 7:9cd16581b578 439
IanBenzMaxim 7:9cd16581b578 440 error_code DS28C40::authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
IanBenzMaxim 7:9cd16581b578 441 Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 442 Page::const_span hmac) {
IanBenzMaxim 7:9cd16581b578 443 return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
IanBenzMaxim 7:9cd16581b578 444 NULL);
IanBenzMaxim 7:9cd16581b578 445 }
IanBenzMaxim 7:9cd16581b578 446
IanBenzMaxim 7:9cd16581b578 447 error_code DS28C40::authenticatedSha256WriteMemory(
IanBenzMaxim 7:9cd16581b578 448 int pageNum, bool useSecretS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 449 Page::const_span hmac, EncryptionChallenge::const_span challenge) {
IanBenzMaxim 7:9cd16581b578 450 return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
IanBenzMaxim 7:9cd16581b578 451 &challenge);
IanBenzMaxim 7:9cd16581b578 452 }
IanBenzMaxim 7:9cd16581b578 453
IanBenzMaxim 7:9cd16581b578 454 error_code DS28C40::authenticatedSha256WriteMemory(
IanBenzMaxim 7:9cd16581b578 455 int pageNum, bool useSecretS, Page::const_span newPageData,
IanBenzMaxim 7:9cd16581b578 456 Page::const_span hmac, const EncryptionChallenge::const_span * challenge) {
IanBenzMaxim 7:9cd16581b578 457 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 458 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 459 }
IanBenzMaxim 7:9cd16581b578 460
IanBenzMaxim 7:9cd16581b578 461 uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size];
IanBenzMaxim 7:9cd16581b578 462 uint_least8_t * requestIt = request;
IanBenzMaxim 7:9cd16581b578 463 *requestIt++ = 0x99;
IanBenzMaxim 7:9cd16581b578 464 *requestIt++ = pageNum;
IanBenzMaxim 7:9cd16581b578 465 *requestIt++ = useSecretS ? 2 : 0;
IanBenzMaxim 7:9cd16581b578 466 requestIt = copy(newPageData.begin(), newPageData.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 467 requestIt = copy(hmac.begin(), hmac.end(), requestIt);
IanBenzMaxim 7:9cd16581b578 468 int delay = writeMemoryTimeMs + computeTimeMs;
IanBenzMaxim 7:9cd16581b578 469 if (challenge) {
IanBenzMaxim 7:9cd16581b578 470 requestIt = copy(challenge->begin(), challenge->end(), requestIt);
IanBenzMaxim 7:9cd16581b578 471 delay += computeTimeMs;
IanBenzMaxim 7:9cd16581b578 472 }
IanBenzMaxim 7:9cd16581b578 473 return runCommand(make_span(request, requestIt), delay);
IanBenzMaxim 7:9cd16581b578 474 }
IanBenzMaxim 7:9cd16581b578 475
IanBenzMaxim 7:9cd16581b578 476 error_code
IanBenzMaxim 7:9cd16581b578 477 DS28C40::computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret,
IanBenzMaxim 7:9cd16581b578 478 KeySecret destinationSecret,
IanBenzMaxim 7:9cd16581b578 479 Page::const_span partialSecret) {
IanBenzMaxim 7:9cd16581b578 480 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 481 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 482 }
IanBenzMaxim 7:9cd16581b578 483
IanBenzMaxim 7:9cd16581b578 484 uint_least8_t request[3 + Page::size];
IanBenzMaxim 7:9cd16581b578 485 request[0] = 0x3C;
IanBenzMaxim 7:9cd16581b578 486 request[1] = pageNum;
IanBenzMaxim 7:9cd16581b578 487 request[2] = (destinationSecret << 2) | masterSecret;
IanBenzMaxim 7:9cd16581b578 488 copy(partialSecret.begin(), partialSecret.end(), request + 3);
IanBenzMaxim 7:9cd16581b578 489 return runCommand(request, writeMemoryTimeMs + computeTimeMs);
IanBenzMaxim 7:9cd16581b578 490 }
IanBenzMaxim 7:9cd16581b578 491
IanBenzMaxim 7:9cd16581b578 492 error_code DS28C40::generateEcc256KeyPair(KeySecret key) {
IanBenzMaxim 7:9cd16581b578 493 if (key == KeySecretS) {
IanBenzMaxim 7:9cd16581b578 494 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 495 }
IanBenzMaxim 7:9cd16581b578 496
IanBenzMaxim 7:9cd16581b578 497 const uint_least8_t request[] = {0xCB, key == KeySecretB};
IanBenzMaxim 7:9cd16581b578 498 return runCommand(request, generateEccKeyPairTimeMs);
IanBenzMaxim 7:9cd16581b578 499 }
IanBenzMaxim 7:9cd16581b578 500
IanBenzMaxim 7:9cd16581b578 501 error_code DS28C40::readRng(span<uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 502 const span<uint_least8_t>::index_type maxDataSize = 64;
IanBenzMaxim 7:9cd16581b578 503 if ((data.size() < 1) || (data.size() > maxDataSize)) {
IanBenzMaxim 7:9cd16581b578 504 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 505 }
IanBenzMaxim 7:9cd16581b578 506
IanBenzMaxim 7:9cd16581b578 507 uint_least8_t buffer[1 + maxDataSize];
IanBenzMaxim 7:9cd16581b578 508 buffer[0] = readRngCmd;
IanBenzMaxim 7:9cd16581b578 509 buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
IanBenzMaxim 7:9cd16581b578 510 span<uint_least8_t> response(buffer, 1 + data.size());
IanBenzMaxim 7:9cd16581b578 511 const error_code result =
IanBenzMaxim 7:9cd16581b578 512 runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
IanBenzMaxim 7:9cd16581b578 513 if (!result) {
IanBenzMaxim 7:9cd16581b578 514 copy(response.begin(), response.end(), data.begin());
IanBenzMaxim 7:9cd16581b578 515 }
IanBenzMaxim 7:9cd16581b578 516 return result;
IanBenzMaxim 7:9cd16581b578 517 }
IanBenzMaxim 7:9cd16581b578 518
IanBenzMaxim 7:9cd16581b578 519 error_code DS28C40::entropyHealthTest() {
IanBenzMaxim 7:9cd16581b578 520 const uint_least8_t request[] = {readRngCmd, 0x80};
IanBenzMaxim 7:9cd16581b578 521 return runCommand(request, trngOnDemandCheckTimeMs);
IanBenzMaxim 7:9cd16581b578 522 }
IanBenzMaxim 7:9cd16581b578 523
IanBenzMaxim 7:9cd16581b578 524 error_code DS28C40::runCommand(span<const uint_least8_t> request, int delayTime,
IanBenzMaxim 7:9cd16581b578 525 span<uint_least8_t> & response) {
IanBenzMaxim 7:9cd16581b578 526 const span<const uint_least8_t>::index_type responseInputSize =
IanBenzMaxim 7:9cd16581b578 527 response.size();
IanBenzMaxim 7:9cd16581b578 528 error_code result = doRunCommand(request, delayTime, response);
IanBenzMaxim 7:9cd16581b578 529 if (result) {
IanBenzMaxim 7:9cd16581b578 530 return result;
IanBenzMaxim 7:9cd16581b578 531 }
IanBenzMaxim 7:9cd16581b578 532 if (response.empty()) {
IanBenzMaxim 7:9cd16581b578 533 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 534 }
IanBenzMaxim 7:9cd16581b578 535 // Parse command result byte.
IanBenzMaxim 7:9cd16581b578 536 switch (response[0]) {
IanBenzMaxim 7:9cd16581b578 537 case 0xAA:
IanBenzMaxim 7:9cd16581b578 538 // Success response.
IanBenzMaxim 7:9cd16581b578 539 if (response.size() != responseInputSize) {
IanBenzMaxim 7:9cd16581b578 540 result = make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 541 }
IanBenzMaxim 7:9cd16581b578 542 break;
IanBenzMaxim 7:9cd16581b578 543
IanBenzMaxim 7:9cd16581b578 544 case 0x00:
IanBenzMaxim 7:9cd16581b578 545 result = make_error_code(AuthenticationError);
IanBenzMaxim 7:9cd16581b578 546 break;
IanBenzMaxim 7:9cd16581b578 547
IanBenzMaxim 7:9cd16581b578 548 default:
IanBenzMaxim 7:9cd16581b578 549 result.assign(response[0], errorCategory());
IanBenzMaxim 7:9cd16581b578 550 break;
IanBenzMaxim 7:9cd16581b578 551 }
IanBenzMaxim 7:9cd16581b578 552 response = response.subspan(1);
IanBenzMaxim 7:9cd16581b578 553 return result;
IanBenzMaxim 7:9cd16581b578 554 }
IanBenzMaxim 7:9cd16581b578 555
IanBenzMaxim 7:9cd16581b578 556 error_code DS28C40::runCommand(span<const uint_least8_t> request,
IanBenzMaxim 7:9cd16581b578 557 int delayTime) {
IanBenzMaxim 7:9cd16581b578 558 uint_least8_t buffer;
IanBenzMaxim 7:9cd16581b578 559 span<uint_least8_t> response(&buffer, 1);
IanBenzMaxim 7:9cd16581b578 560 return runCommand(request, delayTime, response);
IanBenzMaxim 7:9cd16581b578 561 }
IanBenzMaxim 7:9cd16581b578 562
IanBenzMaxim 7:9cd16581b578 563 const error_category & DS28C40::errorCategory() {
IanBenzMaxim 7:9cd16581b578 564 static class : public error_category {
IanBenzMaxim 7:9cd16581b578 565 public:
IanBenzMaxim 7:9cd16581b578 566 virtual const char * name() const { return "DS28C40"; }
IanBenzMaxim 7:9cd16581b578 567
IanBenzMaxim 7:9cd16581b578 568 virtual std::string message(int condition) const {
IanBenzMaxim 7:9cd16581b578 569 switch (condition) {
IanBenzMaxim 7:9cd16581b578 570 case InvalidOperationError:
IanBenzMaxim 7:9cd16581b578 571 return "Invalid Operation Error";
IanBenzMaxim 7:9cd16581b578 572
IanBenzMaxim 7:9cd16581b578 573 case InvalidParameterError:
IanBenzMaxim 7:9cd16581b578 574 return "Invalid Parameter Error";
IanBenzMaxim 7:9cd16581b578 575
IanBenzMaxim 7:9cd16581b578 576 case InvalidSequenceError:
IanBenzMaxim 7:9cd16581b578 577 return "Invalid Sequence Error";
IanBenzMaxim 7:9cd16581b578 578
IanBenzMaxim 7:9cd16581b578 579 case AuthenticationError:
IanBenzMaxim 7:9cd16581b578 580 return "Authentication Error";
IanBenzMaxim 7:9cd16581b578 581
IanBenzMaxim 7:9cd16581b578 582 case InternalError:
IanBenzMaxim 7:9cd16581b578 583 return "Internal Error";
IanBenzMaxim 7:9cd16581b578 584
IanBenzMaxim 7:9cd16581b578 585 case DeviceDisabledError:
IanBenzMaxim 7:9cd16581b578 586 return "Device Disabled Error";
IanBenzMaxim 7:9cd16581b578 587
IanBenzMaxim 7:9cd16581b578 588 case InvalidResponseError:
IanBenzMaxim 7:9cd16581b578 589 return "Invalid Response Error";
IanBenzMaxim 7:9cd16581b578 590 }
IanBenzMaxim 7:9cd16581b578 591 return defaultErrorMessage(condition);
IanBenzMaxim 7:9cd16581b578 592 }
IanBenzMaxim 7:9cd16581b578 593 } instance;
IanBenzMaxim 7:9cd16581b578 594 return instance;
IanBenzMaxim 7:9cd16581b578 595 }
IanBenzMaxim 7:9cd16581b578 596
IanBenzMaxim 7:9cd16581b578 597 error_code computeMultiblockHash(DS28C40 & device,
IanBenzMaxim 7:9cd16581b578 598 span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 599 error_code result;
IanBenzMaxim 7:9cd16581b578 600 span<const uint_least8_t>::index_type dataIdx = 0;
IanBenzMaxim 7:9cd16581b578 601 while (dataIdx < data.size() && !result) {
IanBenzMaxim 7:9cd16581b578 602 const span<const uint_least8_t>::index_type remainingSize =
IanBenzMaxim 7:9cd16581b578 603 data.size() - dataIdx;
IanBenzMaxim 7:9cd16581b578 604 const span<const uint_least8_t>::index_type chunkSize =
IanBenzMaxim 7:9cd16581b578 605 std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
IanBenzMaxim 7:9cd16581b578 606 result =
IanBenzMaxim 7:9cd16581b578 607 device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
IanBenzMaxim 7:9cd16581b578 608 data.subspan(dataIdx, chunkSize));
IanBenzMaxim 7:9cd16581b578 609 dataIdx += chunkSize;
IanBenzMaxim 7:9cd16581b578 610 }
IanBenzMaxim 7:9cd16581b578 611 return result;
IanBenzMaxim 7:9cd16581b578 612 }
IanBenzMaxim 7:9cd16581b578 613
IanBenzMaxim 7:9cd16581b578 614 error_code readRomIdAndManId(DS28C40 & device, RomId::span romId,
IanBenzMaxim 7:9cd16581b578 615 ManId::span manId) {
IanBenzMaxim 7:9cd16581b578 616 DS28C40::Page::array page;
IanBenzMaxim 7:9cd16581b578 617 error_code result = device.readMemory(DS28C40::romOptionsPage, page);
IanBenzMaxim 7:9cd16581b578 618 if (!result) {
IanBenzMaxim 7:9cd16581b578 619 const DS28C40::RomOptions romOptions(page);
IanBenzMaxim 7:9cd16581b578 620 copy(romOptions.romId(), romId);
IanBenzMaxim 7:9cd16581b578 621 copy(romOptions.manId(), manId);
IanBenzMaxim 7:9cd16581b578 622 }
IanBenzMaxim 7:9cd16581b578 623 return result;
IanBenzMaxim 7:9cd16581b578 624 }
IanBenzMaxim 7:9cd16581b578 625
IanBenzMaxim 7:9cd16581b578 626 static void setAnonymous(RomId::span romId) {
IanBenzMaxim 7:9cd16581b578 627 std::fill(romId.begin(), romId.end(), 0xFF);
IanBenzMaxim 7:9cd16581b578 628 }
IanBenzMaxim 7:9cd16581b578 629
IanBenzMaxim 7:9cd16581b578 630 DS28C40::PageAuthenticationData &
IanBenzMaxim 7:9cd16581b578 631 DS28C40::PageAuthenticationData::setAnonymousRomId() {
IanBenzMaxim 7:9cd16581b578 632 setAnonymous(romId());
IanBenzMaxim 7:9cd16581b578 633 return *this;
IanBenzMaxim 7:9cd16581b578 634 }
IanBenzMaxim 7:9cd16581b578 635
IanBenzMaxim 7:9cd16581b578 636 DS28C40::ComputeSecretData::ComputeSecretData() : data() {
IanBenzMaxim 7:9cd16581b578 637 setPageNum(0);
IanBenzMaxim 7:9cd16581b578 638 setManId(ManId::array());
IanBenzMaxim 7:9cd16581b578 639 }
IanBenzMaxim 7:9cd16581b578 640
IanBenzMaxim 7:9cd16581b578 641 DS28C40::ComputeSecretData &
IanBenzMaxim 7:9cd16581b578 642 DS28C40::ComputeSecretData::setManId(ManId::const_span manId) {
IanBenzMaxim 7:9cd16581b578 643 ManId::array validatedManId;
IanBenzMaxim 7:9cd16581b578 644 copy(manId, make_span(validatedManId));
IanBenzMaxim 7:9cd16581b578 645 validatedManId[1] |= 0x80;
IanBenzMaxim 7:9cd16581b578 646 data.setManId(validatedManId);
IanBenzMaxim 7:9cd16581b578 647 return *this;
IanBenzMaxim 7:9cd16581b578 648 }
IanBenzMaxim 7:9cd16581b578 649
IanBenzMaxim 7:9cd16581b578 650 DS28C40::DecryptionHmacData & DS28C40::DecryptionHmacData::setAnonymousRomId() {
IanBenzMaxim 7:9cd16581b578 651 setAnonymous(romId());
IanBenzMaxim 7:9cd16581b578 652 return *this;
IanBenzMaxim 7:9cd16581b578 653 }
IanBenzMaxim 7:9cd16581b578 654
IanBenzMaxim 7:9cd16581b578 655 } // namespace MaximInterfaceDevices