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) 2017 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 <algorithm>
IanBenzMaxim 7:9cd16581b578 34 #include <MaximInterfaceCore/Error.hpp>
IanBenzMaxim 7:9cd16581b578 35 #include <MaximInterfaceCore/I2CMaster.hpp>
IanBenzMaxim 7:9cd16581b578 36 #include <MaximInterfaceCore/RomId.hpp>
IanBenzMaxim 7:9cd16581b578 37 #include "DS28C36_DS2476.hpp"
IanBenzMaxim 7:9cd16581b578 38
IanBenzMaxim 7:9cd16581b578 39 namespace MaximInterfaceDevices {
IanBenzMaxim 7:9cd16581b578 40
IanBenzMaxim 7:9cd16581b578 41 using namespace Core;
IanBenzMaxim 7:9cd16581b578 42 using namespace Ecc256;
IanBenzMaxim 7:9cd16581b578 43 using std::copy;
IanBenzMaxim 7:9cd16581b578 44
IanBenzMaxim 7:9cd16581b578 45 static error_code convertResultByte(uint_least8_t resultByte) {
IanBenzMaxim 7:9cd16581b578 46 error_code errorCode;
IanBenzMaxim 7:9cd16581b578 47 if (resultByte != 0xAA) {
IanBenzMaxim 7:9cd16581b578 48 errorCode.assign((resultByte == 0x00)
IanBenzMaxim 7:9cd16581b578 49 ? static_cast<int>(DS28C36::AuthenticationError)
IanBenzMaxim 7:9cd16581b578 50 : resultByte,
IanBenzMaxim 7:9cd16581b578 51 DS28C36::errorCategory());
IanBenzMaxim 7:9cd16581b578 52 }
IanBenzMaxim 7:9cd16581b578 53 return errorCode;
IanBenzMaxim 7:9cd16581b578 54 }
IanBenzMaxim 7:9cd16581b578 55
IanBenzMaxim 7:9cd16581b578 56 const int DS28C36::publicKeyAxPage;
IanBenzMaxim 7:9cd16581b578 57 const int DS28C36::publicKeyAyPage;
IanBenzMaxim 7:9cd16581b578 58 const int DS28C36::publicKeyBxPage;
IanBenzMaxim 7:9cd16581b578 59 const int DS28C36::publicKeyByPage;
IanBenzMaxim 7:9cd16581b578 60 const int DS28C36::publicKeyCxPage;
IanBenzMaxim 7:9cd16581b578 61 const int DS28C36::publicKeyCyPage;
IanBenzMaxim 7:9cd16581b578 62 const int DS28C36::privateKeyAPage;
IanBenzMaxim 7:9cd16581b578 63 const int DS28C36::privateKeyBPage;
IanBenzMaxim 7:9cd16581b578 64 const int DS28C36::privateKeyCPage;
IanBenzMaxim 7:9cd16581b578 65 const int DS28C36::secretAPage;
IanBenzMaxim 7:9cd16581b578 66 const int DS28C36::secretBPage;
IanBenzMaxim 7:9cd16581b578 67 const int DS28C36::decrementCounterPage;
IanBenzMaxim 7:9cd16581b578 68 const int DS28C36::romOptionsPage;
IanBenzMaxim 7:9cd16581b578 69 const int DS28C36::gpioControlPage;
IanBenzMaxim 7:9cd16581b578 70 const int DS28C36::publicKeySxPage;
IanBenzMaxim 7:9cd16581b578 71 const int DS28C36::publicKeySyPage;
IanBenzMaxim 7:9cd16581b578 72 const int DS28C36::memoryPages;
IanBenzMaxim 7:9cd16581b578 73
IanBenzMaxim 7:9cd16581b578 74 error_code DS28C36::writeMemory(int pageNum, Page::const_span page) {
IanBenzMaxim 7:9cd16581b578 75 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 76 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 77 }
IanBenzMaxim 7:9cd16581b578 78
IanBenzMaxim 7:9cd16581b578 79 uint_least8_t buffer[1 + Page::size];
IanBenzMaxim 7:9cd16581b578 80 buffer[0] = pageNum;
IanBenzMaxim 7:9cd16581b578 81 copy(page.begin(), page.end(), buffer + 1);
IanBenzMaxim 7:9cd16581b578 82 error_code result = writeCommand(0x96, buffer);
IanBenzMaxim 7:9cd16581b578 83 if (!result) {
IanBenzMaxim 7:9cd16581b578 84 sleep(writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 85 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 86 if (!result) {
IanBenzMaxim 7:9cd16581b578 87 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 88 }
IanBenzMaxim 7:9cd16581b578 89 }
IanBenzMaxim 7:9cd16581b578 90 return result;
IanBenzMaxim 7:9cd16581b578 91 }
IanBenzMaxim 7:9cd16581b578 92
IanBenzMaxim 7:9cd16581b578 93 error_code DS28C36::readMemory(int pageNum, Page::span page) {
IanBenzMaxim 7:9cd16581b578 94 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 95 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 96 }
IanBenzMaxim 7:9cd16581b578 97
IanBenzMaxim 7:9cd16581b578 98 const uint_least8_t parameter = pageNum;
IanBenzMaxim 7:9cd16581b578 99 error_code result = writeCommand(0x69, make_span(&parameter, 1));
IanBenzMaxim 7:9cd16581b578 100 if (!result) {
IanBenzMaxim 7:9cd16581b578 101 sleep(readMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 102 array<uint_least8_t, 1 + Page::size> response;
IanBenzMaxim 7:9cd16581b578 103 result = readFixedLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 104 if (!result) {
IanBenzMaxim 7:9cd16581b578 105 result = convertResultByte(response[0]);
IanBenzMaxim 7:9cd16581b578 106 copy(response.begin() + 1, response.end(), page.begin());
IanBenzMaxim 7:9cd16581b578 107 }
IanBenzMaxim 7:9cd16581b578 108 }
IanBenzMaxim 7:9cd16581b578 109 return result;
IanBenzMaxim 7:9cd16581b578 110 }
IanBenzMaxim 7:9cd16581b578 111
IanBenzMaxim 7:9cd16581b578 112 error_code DS28C36::writeBuffer(span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 113 return writeCommand(0x87, data);
IanBenzMaxim 7:9cd16581b578 114 }
IanBenzMaxim 7:9cd16581b578 115
IanBenzMaxim 7:9cd16581b578 116 error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) {
IanBenzMaxim 7:9cd16581b578 117 error_code result = writeCommand(0x5A);
IanBenzMaxim 7:9cd16581b578 118 if (!result) {
IanBenzMaxim 7:9cd16581b578 119 data.resize(80);
IanBenzMaxim 7:9cd16581b578 120 span<uint_least8_t> dataSpan(data);
IanBenzMaxim 7:9cd16581b578 121 result = readVariableLengthResponse(dataSpan);
IanBenzMaxim 7:9cd16581b578 122 if (result) {
IanBenzMaxim 7:9cd16581b578 123 data.clear();
IanBenzMaxim 7:9cd16581b578 124 } else {
IanBenzMaxim 7:9cd16581b578 125 data.resize(dataSpan.size());
IanBenzMaxim 7:9cd16581b578 126 }
IanBenzMaxim 7:9cd16581b578 127 }
IanBenzMaxim 7:9cd16581b578 128 return result;
IanBenzMaxim 7:9cd16581b578 129 }
IanBenzMaxim 7:9cd16581b578 130
IanBenzMaxim 7:9cd16581b578 131 error_code DS28C36::readPageProtection(int pageNum,
IanBenzMaxim 7:9cd16581b578 132 PageProtection & protection) {
IanBenzMaxim 7:9cd16581b578 133 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 134 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 135 }
IanBenzMaxim 7:9cd16581b578 136
IanBenzMaxim 7:9cd16581b578 137 uint_least8_t buffer = pageNum;
IanBenzMaxim 7:9cd16581b578 138 error_code result = writeCommand(0xAA, make_span(&buffer, 1));
IanBenzMaxim 7:9cd16581b578 139 if (!result) {
IanBenzMaxim 7:9cd16581b578 140 sleep(readMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 141 result = readFixedLengthResponse(make_span(&buffer, 1));
IanBenzMaxim 7:9cd16581b578 142 if (!result) {
IanBenzMaxim 7:9cd16581b578 143 protection = buffer;
IanBenzMaxim 7:9cd16581b578 144 }
IanBenzMaxim 7:9cd16581b578 145 }
IanBenzMaxim 7:9cd16581b578 146 return result;
IanBenzMaxim 7:9cd16581b578 147 }
IanBenzMaxim 7:9cd16581b578 148
IanBenzMaxim 7:9cd16581b578 149 error_code DS28C36::setPageProtection(int pageNum,
IanBenzMaxim 7:9cd16581b578 150 const PageProtection & protection) {
IanBenzMaxim 7:9cd16581b578 151 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 152 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 153 }
IanBenzMaxim 7:9cd16581b578 154
IanBenzMaxim 7:9cd16581b578 155 uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum),
IanBenzMaxim 7:9cd16581b578 156 static_cast<uint_least8_t>(protection.to_ulong())};
IanBenzMaxim 7:9cd16581b578 157 error_code result = writeCommand(0xC3, buffer);
IanBenzMaxim 7:9cd16581b578 158 if (!result) {
IanBenzMaxim 7:9cd16581b578 159 sleep(writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 160 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 161 if (!result) {
IanBenzMaxim 7:9cd16581b578 162 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 163 }
IanBenzMaxim 7:9cd16581b578 164 }
IanBenzMaxim 7:9cd16581b578 165 return result;
IanBenzMaxim 7:9cd16581b578 166 }
IanBenzMaxim 7:9cd16581b578 167
IanBenzMaxim 7:9cd16581b578 168 error_code DS28C36::decrementCounter() {
IanBenzMaxim 7:9cd16581b578 169 error_code result = writeCommand(0xC9);
IanBenzMaxim 7:9cd16581b578 170 if (!result) {
IanBenzMaxim 7:9cd16581b578 171 sleep(writeMemoryTimeMs);
IanBenzMaxim 7:9cd16581b578 172 uint_least8_t response;
IanBenzMaxim 7:9cd16581b578 173 result = readFixedLengthResponse(make_span(&response, 1));
IanBenzMaxim 7:9cd16581b578 174 if (!result) {
IanBenzMaxim 7:9cd16581b578 175 result = convertResultByte(response);
IanBenzMaxim 7:9cd16581b578 176 }
IanBenzMaxim 7:9cd16581b578 177 }
IanBenzMaxim 7:9cd16581b578 178 return result;
IanBenzMaxim 7:9cd16581b578 179 }
IanBenzMaxim 7:9cd16581b578 180
IanBenzMaxim 7:9cd16581b578 181 error_code DS28C36::readRng(span<uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 182 if ((data.size() < 1) || (data.size() > 64)) {
IanBenzMaxim 7:9cd16581b578 183 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 184 }
IanBenzMaxim 7:9cd16581b578 185
IanBenzMaxim 7:9cd16581b578 186 data[0] = static_cast<uint_least8_t>(data.size() - 1);
IanBenzMaxim 7:9cd16581b578 187 error_code result = writeCommand(0xD2, data.first(1));
IanBenzMaxim 7:9cd16581b578 188 if (!result) {
IanBenzMaxim 7:9cd16581b578 189 sleep(sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 190 result = readFixedLengthResponse(data);
IanBenzMaxim 7:9cd16581b578 191 }
IanBenzMaxim 7:9cd16581b578 192 return result;
IanBenzMaxim 7:9cd16581b578 193 }
IanBenzMaxim 7:9cd16581b578 194
IanBenzMaxim 7:9cd16581b578 195 error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
IanBenzMaxim 7:9cd16581b578 196 EncryptionChallenge::span challenge,
IanBenzMaxim 7:9cd16581b578 197 Page::span data) {
IanBenzMaxim 7:9cd16581b578 198 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 199 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 200 }
IanBenzMaxim 7:9cd16581b578 201
IanBenzMaxim 7:9cd16581b578 202 const uint_least8_t parameter = (secretNum << 6) | pageNum;
IanBenzMaxim 7:9cd16581b578 203 error_code result = writeCommand(0x4B, make_span(&parameter, 1));
IanBenzMaxim 7:9cd16581b578 204 if (!result) {
IanBenzMaxim 7:9cd16581b578 205 sleep(readMemoryTimeMs + sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 206 uint_least8_t response[1 + EncryptionChallenge::size + Page::size];
IanBenzMaxim 7:9cd16581b578 207 result = readFixedLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 208 if (!result) {
IanBenzMaxim 7:9cd16581b578 209 result = convertResultByte(response[0]);
IanBenzMaxim 7:9cd16581b578 210 const uint_least8_t * begin = response + 1;
IanBenzMaxim 7:9cd16581b578 211 const uint_least8_t * end = begin + challenge.size();
IanBenzMaxim 7:9cd16581b578 212 copy(begin, end, challenge.begin());
IanBenzMaxim 7:9cd16581b578 213 begin = end;
IanBenzMaxim 7:9cd16581b578 214 end = begin + data.size();
IanBenzMaxim 7:9cd16581b578 215 copy(begin, end, data.begin());
IanBenzMaxim 7:9cd16581b578 216 }
IanBenzMaxim 7:9cd16581b578 217 }
IanBenzMaxim 7:9cd16581b578 218 return result;
IanBenzMaxim 7:9cd16581b578 219 }
IanBenzMaxim 7:9cd16581b578 220
IanBenzMaxim 7:9cd16581b578 221 error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
IanBenzMaxim 7:9cd16581b578 222 AuthType authType) {
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 uint_least8_t parameter = (authType << 5) | pageNum;
IanBenzMaxim 7:9cd16581b578 228 return writeCommand(0xA5, make_span(&parameter, 1));
IanBenzMaxim 7:9cd16581b578 229 }
IanBenzMaxim 7:9cd16581b578 230
IanBenzMaxim 7:9cd16581b578 231 error_code
IanBenzMaxim 7:9cd16581b578 232 DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum,
IanBenzMaxim 7:9cd16581b578 233 Signature::span signature) {
IanBenzMaxim 7:9cd16581b578 234 AuthType authType;
IanBenzMaxim 7:9cd16581b578 235 switch (keyNum) {
IanBenzMaxim 7:9cd16581b578 236 case KeyNumA:
IanBenzMaxim 7:9cd16581b578 237 authType = EcdsaWithKeyA;
IanBenzMaxim 7:9cd16581b578 238 break;
IanBenzMaxim 7:9cd16581b578 239 case KeyNumB:
IanBenzMaxim 7:9cd16581b578 240 authType = EcdsaWithKeyB;
IanBenzMaxim 7:9cd16581b578 241 break;
IanBenzMaxim 7:9cd16581b578 242 case KeyNumC:
IanBenzMaxim 7:9cd16581b578 243 authType = EcdsaWithKeyC;
IanBenzMaxim 7:9cd16581b578 244 break;
IanBenzMaxim 7:9cd16581b578 245 default:
IanBenzMaxim 7:9cd16581b578 246 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 247 }
IanBenzMaxim 7:9cd16581b578 248 error_code result = computeAndReadPageAuthentication(pageNum, authType);
IanBenzMaxim 7:9cd16581b578 249 if (!result) {
IanBenzMaxim 7:9cd16581b578 250 sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs);
IanBenzMaxim 7:9cd16581b578 251 uint_least8_t response[1 + 2 * Scalar::size];
IanBenzMaxim 7:9cd16581b578 252 result = readFixedLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 253 if (!result) {
IanBenzMaxim 7:9cd16581b578 254 result = convertResultByte(response[0]);
IanBenzMaxim 7:9cd16581b578 255 const uint_least8_t * begin = response + 1;
IanBenzMaxim 7:9cd16581b578 256 const uint_least8_t * end = begin + signature.s.size();
IanBenzMaxim 7:9cd16581b578 257 copy(begin, end, signature.s.begin());
IanBenzMaxim 7:9cd16581b578 258 begin = end;
IanBenzMaxim 7:9cd16581b578 259 end = begin + signature.r.size();
IanBenzMaxim 7:9cd16581b578 260 copy(begin, end, signature.r.begin());
IanBenzMaxim 7:9cd16581b578 261 }
IanBenzMaxim 7:9cd16581b578 262 }
IanBenzMaxim 7:9cd16581b578 263 return result;
IanBenzMaxim 7:9cd16581b578 264 }
IanBenzMaxim 7:9cd16581b578 265
IanBenzMaxim 7:9cd16581b578 266 error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
IanBenzMaxim 7:9cd16581b578 267 SecretNum secretNum,
IanBenzMaxim 7:9cd16581b578 268 Page::span hmac) {
IanBenzMaxim 7:9cd16581b578 269 AuthType authType;
IanBenzMaxim 7:9cd16581b578 270 switch (secretNum) {
IanBenzMaxim 7:9cd16581b578 271 case SecretNumA:
IanBenzMaxim 7:9cd16581b578 272 authType = HmacWithSecretA;
IanBenzMaxim 7:9cd16581b578 273 break;
IanBenzMaxim 7:9cd16581b578 274 case SecretNumB:
IanBenzMaxim 7:9cd16581b578 275 authType = HmacWithSecretB;
IanBenzMaxim 7:9cd16581b578 276 break;
IanBenzMaxim 7:9cd16581b578 277 case SecretNumS:
IanBenzMaxim 7:9cd16581b578 278 authType = HmacWithSecretS;
IanBenzMaxim 7:9cd16581b578 279 break;
IanBenzMaxim 7:9cd16581b578 280 default:
IanBenzMaxim 7:9cd16581b578 281 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 282 }
IanBenzMaxim 7:9cd16581b578 283 error_code result = computeAndReadPageAuthentication(pageNum, authType);
IanBenzMaxim 7:9cd16581b578 284 if (!result) {
IanBenzMaxim 7:9cd16581b578 285 sleep(readMemoryTimeMs + sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 286 array<uint_least8_t, 1 + Page::size> response;
IanBenzMaxim 7:9cd16581b578 287 result = readFixedLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 288 if (!result) {
IanBenzMaxim 7:9cd16581b578 289 result = convertResultByte(response[0]);
IanBenzMaxim 7:9cd16581b578 290 copy(response.begin() + 1, response.end(), hmac.begin());
IanBenzMaxim 7:9cd16581b578 291 }
IanBenzMaxim 7:9cd16581b578 292 }
IanBenzMaxim 7:9cd16581b578 293 return result;
IanBenzMaxim 7:9cd16581b578 294 }
IanBenzMaxim 7:9cd16581b578 295
IanBenzMaxim 7:9cd16581b578 296 error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
IanBenzMaxim 7:9cd16581b578 297 SecretNum secretNum,
IanBenzMaxim 7:9cd16581b578 298 Page::const_span page) {
IanBenzMaxim 7:9cd16581b578 299 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 300 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 301 }
IanBenzMaxim 7:9cd16581b578 302
IanBenzMaxim 7:9cd16581b578 303 uint_least8_t buffer[1 + Page::size];
IanBenzMaxim 7:9cd16581b578 304 buffer[0] = (secretNum << 6) | pageNum;
IanBenzMaxim 7:9cd16581b578 305 copy(page.begin(), page.end(), buffer + 1);
IanBenzMaxim 7:9cd16581b578 306 error_code result = writeCommand(0x99, buffer);
IanBenzMaxim 7:9cd16581b578 307 if (!result) {
IanBenzMaxim 7:9cd16581b578 308 sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
IanBenzMaxim 7:9cd16581b578 309 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 310 if (!result) {
IanBenzMaxim 7:9cd16581b578 311 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 312 }
IanBenzMaxim 7:9cd16581b578 313 }
IanBenzMaxim 7:9cd16581b578 314 return result;
IanBenzMaxim 7:9cd16581b578 315 }
IanBenzMaxim 7:9cd16581b578 316
IanBenzMaxim 7:9cd16581b578 317 error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
IanBenzMaxim 7:9cd16581b578 318 SecretNum dsecretNum,
IanBenzMaxim 7:9cd16581b578 319 bool writeProtectEnable) {
IanBenzMaxim 7:9cd16581b578 320 // User pages only
IanBenzMaxim 7:9cd16581b578 321 if (pageNum < 0 || pageNum > 15) {
IanBenzMaxim 7:9cd16581b578 322 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 323 }
IanBenzMaxim 7:9cd16581b578 324
IanBenzMaxim 7:9cd16581b578 325 uint_least8_t buffer[] = {
IanBenzMaxim 7:9cd16581b578 326 static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) |
IanBenzMaxim 7:9cd16581b578 327 pageNum),
IanBenzMaxim 7:9cd16581b578 328 static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)};
IanBenzMaxim 7:9cd16581b578 329 error_code result = writeCommand(0x3C, buffer);
IanBenzMaxim 7:9cd16581b578 330 if (!result) {
IanBenzMaxim 7:9cd16581b578 331 sleep(sha256ComputationTimeMs +
IanBenzMaxim 7:9cd16581b578 332 ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
IanBenzMaxim 7:9cd16581b578 333 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 334 if (!result) {
IanBenzMaxim 7:9cd16581b578 335 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 336 }
IanBenzMaxim 7:9cd16581b578 337 }
IanBenzMaxim 7:9cd16581b578 338 return result;
IanBenzMaxim 7:9cd16581b578 339 }
IanBenzMaxim 7:9cd16581b578 340
IanBenzMaxim 7:9cd16581b578 341 error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
IanBenzMaxim 7:9cd16581b578 342 bool writeProtectEnable) {
IanBenzMaxim 7:9cd16581b578 343 if (keyNum == KeyNumS) {
IanBenzMaxim 7:9cd16581b578 344 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 345 }
IanBenzMaxim 7:9cd16581b578 346
IanBenzMaxim 7:9cd16581b578 347 uint_least8_t buffer = keyNum;
IanBenzMaxim 7:9cd16581b578 348 if (writeProtectEnable) {
IanBenzMaxim 7:9cd16581b578 349 buffer |= 0x80;
IanBenzMaxim 7:9cd16581b578 350 }
IanBenzMaxim 7:9cd16581b578 351 error_code result = writeCommand(0xCB, make_span(&buffer, 1));
IanBenzMaxim 7:9cd16581b578 352 if (!result) {
IanBenzMaxim 7:9cd16581b578 353 sleep(generateEccKeyPairTimeMs);
IanBenzMaxim 7:9cd16581b578 354 result = readFixedLengthResponse(make_span(&buffer, 1));
IanBenzMaxim 7:9cd16581b578 355 if (!result) {
IanBenzMaxim 7:9cd16581b578 356 result = convertResultByte(buffer);
IanBenzMaxim 7:9cd16581b578 357 }
IanBenzMaxim 7:9cd16581b578 358 }
IanBenzMaxim 7:9cd16581b578 359 return result;
IanBenzMaxim 7:9cd16581b578 360 }
IanBenzMaxim 7:9cd16581b578 361
IanBenzMaxim 7:9cd16581b578 362 error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
IanBenzMaxim 7:9cd16581b578 363 span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 364 const span<const uint_least8_t>::index_type maxDataSize = 64;
IanBenzMaxim 7:9cd16581b578 365
IanBenzMaxim 7:9cd16581b578 366 if (data.size() < 1 || data.size() > maxDataSize) {
IanBenzMaxim 7:9cd16581b578 367 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 368 }
IanBenzMaxim 7:9cd16581b578 369
IanBenzMaxim 7:9cd16581b578 370 uint_least8_t buffer[1 + maxDataSize];
IanBenzMaxim 7:9cd16581b578 371 buffer[0] = 0;
IanBenzMaxim 7:9cd16581b578 372 if (firstBlock) {
IanBenzMaxim 7:9cd16581b578 373 buffer[0] |= 0x40;
IanBenzMaxim 7:9cd16581b578 374 }
IanBenzMaxim 7:9cd16581b578 375 if (lastBlock) {
IanBenzMaxim 7:9cd16581b578 376 buffer[0] |= 0x80;
IanBenzMaxim 7:9cd16581b578 377 }
IanBenzMaxim 7:9cd16581b578 378 copy(data.begin(), data.end(), buffer + 1);
IanBenzMaxim 7:9cd16581b578 379 error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1));
IanBenzMaxim 7:9cd16581b578 380 if (!result) {
IanBenzMaxim 7:9cd16581b578 381 sleep(sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 382 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 383 if (!result) {
IanBenzMaxim 7:9cd16581b578 384 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 385 }
IanBenzMaxim 7:9cd16581b578 386 }
IanBenzMaxim 7:9cd16581b578 387 return result;
IanBenzMaxim 7:9cd16581b578 388 }
IanBenzMaxim 7:9cd16581b578 389
IanBenzMaxim 7:9cd16581b578 390 error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
IanBenzMaxim 7:9cd16581b578 391 Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 392 PioState pioa, PioState piob) {
IanBenzMaxim 7:9cd16581b578 393 uint_least8_t buffer[1 + 2 * Scalar::size];
IanBenzMaxim 7:9cd16581b578 394 buffer[0] = keyNum | (hashType << 2);
IanBenzMaxim 7:9cd16581b578 395 if (pioa != Unchanged) {
IanBenzMaxim 7:9cd16581b578 396 buffer[0] |= 0x20;
IanBenzMaxim 7:9cd16581b578 397 }
IanBenzMaxim 7:9cd16581b578 398 if (pioa == Conducting) {
IanBenzMaxim 7:9cd16581b578 399 buffer[0] |= 0x10;
IanBenzMaxim 7:9cd16581b578 400 }
IanBenzMaxim 7:9cd16581b578 401 if (piob != Unchanged) {
IanBenzMaxim 7:9cd16581b578 402 buffer[0] |= 0x80;
IanBenzMaxim 7:9cd16581b578 403 }
IanBenzMaxim 7:9cd16581b578 404 if (piob == Conducting) {
IanBenzMaxim 7:9cd16581b578 405 buffer[0] |= 0x40;
IanBenzMaxim 7:9cd16581b578 406 }
IanBenzMaxim 7:9cd16581b578 407 uint_least8_t * bufferIt =
IanBenzMaxim 7:9cd16581b578 408 copy(signature.r.begin(), signature.r.end(), buffer + 1);
IanBenzMaxim 7:9cd16581b578 409 copy(signature.s.begin(), signature.s.end(), bufferIt);
IanBenzMaxim 7:9cd16581b578 410 error_code result = writeCommand(0x59, buffer);
IanBenzMaxim 7:9cd16581b578 411 if (!result) {
IanBenzMaxim 7:9cd16581b578 412 sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
IanBenzMaxim 7:9cd16581b578 413 ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
IanBenzMaxim 7:9cd16581b578 414 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 415 if (!result) {
IanBenzMaxim 7:9cd16581b578 416 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 417 }
IanBenzMaxim 7:9cd16581b578 418 }
IanBenzMaxim 7:9cd16581b578 419 return result;
IanBenzMaxim 7:9cd16581b578 420 }
IanBenzMaxim 7:9cd16581b578 421
IanBenzMaxim 7:9cd16581b578 422 error_code
IanBenzMaxim 7:9cd16581b578 423 DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
IanBenzMaxim 7:9cd16581b578 424 int csOffset,
IanBenzMaxim 7:9cd16581b578 425 Signature::const_span signature) {
IanBenzMaxim 7:9cd16581b578 426 if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) ||
IanBenzMaxim 7:9cd16581b578 427 (csOffset > 31)) {
IanBenzMaxim 7:9cd16581b578 428 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 429 }
IanBenzMaxim 7:9cd16581b578 430
IanBenzMaxim 7:9cd16581b578 431 uint_least8_t buffer[1 + 2 * Scalar::size];
IanBenzMaxim 7:9cd16581b578 432 buffer[0] = (csOffset << 3) | (keyNum << 2);
IanBenzMaxim 7:9cd16581b578 433 if (ecdh) {
IanBenzMaxim 7:9cd16581b578 434 buffer[0] |= 0x02;
IanBenzMaxim 7:9cd16581b578 435 }
IanBenzMaxim 7:9cd16581b578 436 if (authWrites) {
IanBenzMaxim 7:9cd16581b578 437 buffer[0] |= 0x01;
IanBenzMaxim 7:9cd16581b578 438 }
IanBenzMaxim 7:9cd16581b578 439 uint_least8_t * bufferIt =
IanBenzMaxim 7:9cd16581b578 440 copy(signature.r.begin(), signature.r.end(), buffer + 1);
IanBenzMaxim 7:9cd16581b578 441 copy(signature.s.begin(), signature.s.end(), bufferIt);
IanBenzMaxim 7:9cd16581b578 442 error_code result = writeCommand(0xA8, buffer);
IanBenzMaxim 7:9cd16581b578 443 if (!result) {
IanBenzMaxim 7:9cd16581b578 444 sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
IanBenzMaxim 7:9cd16581b578 445 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 446 if (!result) {
IanBenzMaxim 7:9cd16581b578 447 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 448 }
IanBenzMaxim 7:9cd16581b578 449 }
IanBenzMaxim 7:9cd16581b578 450 return result;
IanBenzMaxim 7:9cd16581b578 451 }
IanBenzMaxim 7:9cd16581b578 452
IanBenzMaxim 7:9cd16581b578 453 error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
IanBenzMaxim 7:9cd16581b578 454 Page::const_span page) {
IanBenzMaxim 7:9cd16581b578 455 if (pageNum < 0 || pageNum >= memoryPages) {
IanBenzMaxim 7:9cd16581b578 456 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 457 }
IanBenzMaxim 7:9cd16581b578 458
IanBenzMaxim 7:9cd16581b578 459 uint_least8_t buffer[1 + Page::size];
IanBenzMaxim 7:9cd16581b578 460 buffer[0] = pageNum;
IanBenzMaxim 7:9cd16581b578 461 copy(page.begin(), page.end(), buffer + 1);
IanBenzMaxim 7:9cd16581b578 462 error_code result = writeCommand(0x89, buffer);
IanBenzMaxim 7:9cd16581b578 463 if (!result) {
IanBenzMaxim 7:9cd16581b578 464 sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
IanBenzMaxim 7:9cd16581b578 465 sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 466 result = readFixedLengthResponse(make_span(buffer, 1));
IanBenzMaxim 7:9cd16581b578 467 if (!result) {
IanBenzMaxim 7:9cd16581b578 468 result = convertResultByte(buffer[0]);
IanBenzMaxim 7:9cd16581b578 469 }
IanBenzMaxim 7:9cd16581b578 470 }
IanBenzMaxim 7:9cd16581b578 471 return result;
IanBenzMaxim 7:9cd16581b578 472 }
IanBenzMaxim 7:9cd16581b578 473
IanBenzMaxim 7:9cd16581b578 474 error_code DS28C36::writeCommand(uint_least8_t command,
IanBenzMaxim 7:9cd16581b578 475 span<const uint_least8_t> parameters) {
IanBenzMaxim 7:9cd16581b578 476 error_code result = master->start(address_);
IanBenzMaxim 7:9cd16581b578 477 if (result) {
IanBenzMaxim 7:9cd16581b578 478 master->stop();
IanBenzMaxim 7:9cd16581b578 479 return result;
IanBenzMaxim 7:9cd16581b578 480 }
IanBenzMaxim 7:9cd16581b578 481 result = master->writeByte(command);
IanBenzMaxim 7:9cd16581b578 482 if (result) {
IanBenzMaxim 7:9cd16581b578 483 master->stop();
IanBenzMaxim 7:9cd16581b578 484 return result;
IanBenzMaxim 7:9cd16581b578 485 }
IanBenzMaxim 7:9cd16581b578 486 if (!parameters.empty()) {
IanBenzMaxim 7:9cd16581b578 487 result = master->writeByte(static_cast<uint_least8_t>(parameters.size()));
IanBenzMaxim 7:9cd16581b578 488 if (result) {
IanBenzMaxim 7:9cd16581b578 489 master->stop();
IanBenzMaxim 7:9cd16581b578 490 return result;
IanBenzMaxim 7:9cd16581b578 491 }
IanBenzMaxim 7:9cd16581b578 492 result = master->writeBlock(parameters);
IanBenzMaxim 7:9cd16581b578 493 if (result) {
IanBenzMaxim 7:9cd16581b578 494 master->stop();
IanBenzMaxim 7:9cd16581b578 495 return result;
IanBenzMaxim 7:9cd16581b578 496 }
IanBenzMaxim 7:9cd16581b578 497 }
IanBenzMaxim 7:9cd16581b578 498 result = master->stop();
IanBenzMaxim 7:9cd16581b578 499 return result;
IanBenzMaxim 7:9cd16581b578 500 }
IanBenzMaxim 7:9cd16581b578 501
IanBenzMaxim 7:9cd16581b578 502 error_code DS28C36::readVariableLengthResponse(span<uint_least8_t> & response) {
IanBenzMaxim 7:9cd16581b578 503 error_code result = master->start(address_ | 1);
IanBenzMaxim 7:9cd16581b578 504 if (result) {
IanBenzMaxim 7:9cd16581b578 505 master->stop();
IanBenzMaxim 7:9cd16581b578 506 return result;
IanBenzMaxim 7:9cd16581b578 507 }
IanBenzMaxim 7:9cd16581b578 508 uint_least8_t length;
IanBenzMaxim 7:9cd16581b578 509 result = master->readByte(I2CMaster::Ack, length);
IanBenzMaxim 7:9cd16581b578 510 if (result) {
IanBenzMaxim 7:9cd16581b578 511 master->stop();
IanBenzMaxim 7:9cd16581b578 512 return result;
IanBenzMaxim 7:9cd16581b578 513 }
IanBenzMaxim 7:9cd16581b578 514 if (length > response.size()) {
IanBenzMaxim 7:9cd16581b578 515 master->stop();
IanBenzMaxim 7:9cd16581b578 516 return make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 517 }
IanBenzMaxim 7:9cd16581b578 518 response = response.first(length);
IanBenzMaxim 7:9cd16581b578 519 if (!response.empty()) {
IanBenzMaxim 7:9cd16581b578 520 result = master->readBlock(I2CMaster::Nack, response);
IanBenzMaxim 7:9cd16581b578 521 if (result) {
IanBenzMaxim 7:9cd16581b578 522 master->stop();
IanBenzMaxim 7:9cd16581b578 523 return result;
IanBenzMaxim 7:9cd16581b578 524 }
IanBenzMaxim 7:9cd16581b578 525 }
IanBenzMaxim 7:9cd16581b578 526 result = master->stop();
IanBenzMaxim 7:9cd16581b578 527 return result;
IanBenzMaxim 7:9cd16581b578 528 }
IanBenzMaxim 7:9cd16581b578 529
IanBenzMaxim 7:9cd16581b578 530 error_code DS28C36::readFixedLengthResponse(span<uint_least8_t> response) {
IanBenzMaxim 7:9cd16581b578 531 const span<uint_least8_t>::index_type requestedResponseSize = response.size();
IanBenzMaxim 7:9cd16581b578 532 error_code result = readVariableLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 533 if (!result && response.size() != requestedResponseSize) {
IanBenzMaxim 7:9cd16581b578 534 result = make_error_code(InvalidResponseError);
IanBenzMaxim 7:9cd16581b578 535 }
IanBenzMaxim 7:9cd16581b578 536 return result;
IanBenzMaxim 7:9cd16581b578 537 }
IanBenzMaxim 7:9cd16581b578 538
IanBenzMaxim 7:9cd16581b578 539 const error_category & DS28C36::errorCategory() {
IanBenzMaxim 7:9cd16581b578 540 static class : public error_category {
IanBenzMaxim 7:9cd16581b578 541 public:
IanBenzMaxim 7:9cd16581b578 542 virtual const char * name() const { return "DS28C36"; }
IanBenzMaxim 7:9cd16581b578 543
IanBenzMaxim 7:9cd16581b578 544 virtual std::string message(int condition) const {
IanBenzMaxim 7:9cd16581b578 545 switch (condition) {
IanBenzMaxim 7:9cd16581b578 546 case ProtectionError:
IanBenzMaxim 7:9cd16581b578 547 return "Protection Error";
IanBenzMaxim 7:9cd16581b578 548
IanBenzMaxim 7:9cd16581b578 549 case InvalidParameterError:
IanBenzMaxim 7:9cd16581b578 550 return "Invalid Parameter Error";
IanBenzMaxim 7:9cd16581b578 551
IanBenzMaxim 7:9cd16581b578 552 case InvalidSequenceError:
IanBenzMaxim 7:9cd16581b578 553 return "Invalid Sequence Error";
IanBenzMaxim 7:9cd16581b578 554
IanBenzMaxim 7:9cd16581b578 555 case InvalidEcdsaInputOrResultError:
IanBenzMaxim 7:9cd16581b578 556 return "Invalid ECDSA Input or Result Error";
IanBenzMaxim 7:9cd16581b578 557
IanBenzMaxim 7:9cd16581b578 558 case AuthenticationError:
IanBenzMaxim 7:9cd16581b578 559 return "Authentication Error";
IanBenzMaxim 7:9cd16581b578 560
IanBenzMaxim 7:9cd16581b578 561 case InvalidResponseError:
IanBenzMaxim 7:9cd16581b578 562 return "Invalid Response Error";
IanBenzMaxim 7:9cd16581b578 563
IanBenzMaxim 7:9cd16581b578 564 default:
IanBenzMaxim 7:9cd16581b578 565 return defaultErrorMessage(condition);
IanBenzMaxim 7:9cd16581b578 566 }
IanBenzMaxim 7:9cd16581b578 567 }
IanBenzMaxim 7:9cd16581b578 568 } instance;
IanBenzMaxim 7:9cd16581b578 569 return instance;
IanBenzMaxim 7:9cd16581b578 570 }
IanBenzMaxim 7:9cd16581b578 571
IanBenzMaxim 7:9cd16581b578 572 error_code DS2476::generateEcdsaSignature(KeyNum keyNum,
IanBenzMaxim 7:9cd16581b578 573 Signature::span signature) {
IanBenzMaxim 7:9cd16581b578 574 if (keyNum == KeyNumS) {
IanBenzMaxim 7:9cd16581b578 575 return make_error_code(InvalidParameterError);
IanBenzMaxim 7:9cd16581b578 576 }
IanBenzMaxim 7:9cd16581b578 577
IanBenzMaxim 7:9cd16581b578 578 const uint_least8_t parameter = keyNum;
IanBenzMaxim 7:9cd16581b578 579 error_code result = writeCommand(0x1E, make_span(&parameter, 1));
IanBenzMaxim 7:9cd16581b578 580 if (!result) {
IanBenzMaxim 7:9cd16581b578 581 sleep(generateEcdsaSignatureTimeMs);
IanBenzMaxim 7:9cd16581b578 582 uint_least8_t response[1 + 2 * Scalar::size];
IanBenzMaxim 7:9cd16581b578 583 result = readFixedLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 584 if (!result) {
IanBenzMaxim 7:9cd16581b578 585 result = convertResultByte(response[0]);
IanBenzMaxim 7:9cd16581b578 586 const uint_least8_t * begin = response + 1;
IanBenzMaxim 7:9cd16581b578 587 const uint_least8_t * end = begin + signature.s.size();
IanBenzMaxim 7:9cd16581b578 588 copy(begin, end, signature.s.begin());
IanBenzMaxim 7:9cd16581b578 589 begin = end;
IanBenzMaxim 7:9cd16581b578 590 end = begin + signature.r.size();
IanBenzMaxim 7:9cd16581b578 591 copy(begin, end, signature.r.begin());
IanBenzMaxim 7:9cd16581b578 592 }
IanBenzMaxim 7:9cd16581b578 593 }
IanBenzMaxim 7:9cd16581b578 594 return result;
IanBenzMaxim 7:9cd16581b578 595 }
IanBenzMaxim 7:9cd16581b578 596
IanBenzMaxim 7:9cd16581b578 597 error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
IanBenzMaxim 7:9cd16581b578 598 uint_least8_t buffer = msecretNum << 4;
IanBenzMaxim 7:9cd16581b578 599 error_code result = writeCommand(0x55, make_span(&buffer, 1));
IanBenzMaxim 7:9cd16581b578 600 if (!result) {
IanBenzMaxim 7:9cd16581b578 601 sleep(sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 602 result = readFixedLengthResponse(make_span(&buffer, 1));
IanBenzMaxim 7:9cd16581b578 603 if (!result) {
IanBenzMaxim 7:9cd16581b578 604 convertResultByte(buffer);
IanBenzMaxim 7:9cd16581b578 605 }
IanBenzMaxim 7:9cd16581b578 606 }
IanBenzMaxim 7:9cd16581b578 607 return result;
IanBenzMaxim 7:9cd16581b578 608 }
IanBenzMaxim 7:9cd16581b578 609
IanBenzMaxim 7:9cd16581b578 610 error_code DS2476::computeSha2Hmac(Page::span hmac) {
IanBenzMaxim 7:9cd16581b578 611 error_code result = writeCommand(0x2D);
IanBenzMaxim 7:9cd16581b578 612 if (!result) {
IanBenzMaxim 7:9cd16581b578 613 sleep(sha256ComputationTimeMs);
IanBenzMaxim 7:9cd16581b578 614 array<uint_least8_t, 1 + Page::size> response;
IanBenzMaxim 7:9cd16581b578 615 result = readFixedLengthResponse(response);
IanBenzMaxim 7:9cd16581b578 616 if (!result) {
IanBenzMaxim 7:9cd16581b578 617 result = convertResultByte(response[0]);
IanBenzMaxim 7:9cd16581b578 618 copy(response.begin() + 1, response.end(), hmac.begin());
IanBenzMaxim 7:9cd16581b578 619 }
IanBenzMaxim 7:9cd16581b578 620 }
IanBenzMaxim 7:9cd16581b578 621 return result;
IanBenzMaxim 7:9cd16581b578 622 }
IanBenzMaxim 7:9cd16581b578 623
IanBenzMaxim 7:9cd16581b578 624 error_code computeMultiblockHash(DS28C36 & ds28c36,
IanBenzMaxim 7:9cd16581b578 625 span<const uint_least8_t> data) {
IanBenzMaxim 7:9cd16581b578 626 error_code result;
IanBenzMaxim 7:9cd16581b578 627 span<const uint_least8_t>::index_type dataIdx = 0;
IanBenzMaxim 7:9cd16581b578 628 while (dataIdx < data.size() && !result) {
IanBenzMaxim 7:9cd16581b578 629 const span<const uint_least8_t>::index_type remainingSize =
IanBenzMaxim 7:9cd16581b578 630 data.size() - dataIdx;
IanBenzMaxim 7:9cd16581b578 631 const span<const uint_least8_t>::index_type chunkSize =
IanBenzMaxim 7:9cd16581b578 632 std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
IanBenzMaxim 7:9cd16581b578 633 result =
IanBenzMaxim 7:9cd16581b578 634 ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
IanBenzMaxim 7:9cd16581b578 635 data.subspan(dataIdx, chunkSize));
IanBenzMaxim 7:9cd16581b578 636 dataIdx += chunkSize;
IanBenzMaxim 7:9cd16581b578 637 }
IanBenzMaxim 7:9cd16581b578 638 return result;
IanBenzMaxim 7:9cd16581b578 639 }
IanBenzMaxim 7:9cd16581b578 640
IanBenzMaxim 7:9cd16581b578 641 error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
IanBenzMaxim 7:9cd16581b578 642 span<const uint_least8_t> data,
IanBenzMaxim 7:9cd16581b578 643 Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 644 DS28C36::PioState pioa,
IanBenzMaxim 7:9cd16581b578 645 DS28C36::PioState piob) {
IanBenzMaxim 7:9cd16581b578 646 error_code result = computeMultiblockHash(ds28c36, data);
IanBenzMaxim 7:9cd16581b578 647 if (!result) {
IanBenzMaxim 7:9cd16581b578 648 result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature,
IanBenzMaxim 7:9cd16581b578 649 pioa, piob);
IanBenzMaxim 7:9cd16581b578 650 }
IanBenzMaxim 7:9cd16581b578 651 return result;
IanBenzMaxim 7:9cd16581b578 652 }
IanBenzMaxim 7:9cd16581b578 653
IanBenzMaxim 7:9cd16581b578 654 error_code verifyEcdsaSignature(DS28C36 & ds28c36,
IanBenzMaxim 7:9cd16581b578 655 PublicKey::const_span publicKey,
IanBenzMaxim 7:9cd16581b578 656 span<const uint_least8_t> data,
IanBenzMaxim 7:9cd16581b578 657 Signature::const_span signature,
IanBenzMaxim 7:9cd16581b578 658 DS28C36::PioState pioa,
IanBenzMaxim 7:9cd16581b578 659 DS28C36::PioState piob) {
IanBenzMaxim 7:9cd16581b578 660 error_code result =
IanBenzMaxim 7:9cd16581b578 661 ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x);
IanBenzMaxim 7:9cd16581b578 662 if (!result) {
IanBenzMaxim 7:9cd16581b578 663 result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y);
IanBenzMaxim 7:9cd16581b578 664 }
IanBenzMaxim 7:9cd16581b578 665 if (!result) {
IanBenzMaxim 7:9cd16581b578 666 result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature,
IanBenzMaxim 7:9cd16581b578 667 pioa, piob);
IanBenzMaxim 7:9cd16581b578 668 }
IanBenzMaxim 7:9cd16581b578 669 return result;
IanBenzMaxim 7:9cd16581b578 670 }
IanBenzMaxim 7:9cd16581b578 671
IanBenzMaxim 7:9cd16581b578 672 error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId,
IanBenzMaxim 7:9cd16581b578 673 ManId::span manId) {
IanBenzMaxim 7:9cd16581b578 674 DS28C36::Page::array page;
IanBenzMaxim 7:9cd16581b578 675 error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, page);
IanBenzMaxim 7:9cd16581b578 676 if (!result) {
IanBenzMaxim 7:9cd16581b578 677 const DS28C36::RomOptions romOptions(page);
IanBenzMaxim 7:9cd16581b578 678 copy(romOptions.romId(), romId);
IanBenzMaxim 7:9cd16581b578 679 copy(romOptions.manId(), manId);
IanBenzMaxim 7:9cd16581b578 680 }
IanBenzMaxim 7:9cd16581b578 681 return result;
IanBenzMaxim 7:9cd16581b578 682 }
IanBenzMaxim 7:9cd16581b578 683
IanBenzMaxim 7:9cd16581b578 684 error_code enableCoprocessor(DS2476 & ds2476) {
IanBenzMaxim 7:9cd16581b578 685 DS2476::Page::array page;
IanBenzMaxim 7:9cd16581b578 686 error_code result = ds2476.readMemory(DS2476::gpioControlPage, page);
IanBenzMaxim 7:9cd16581b578 687 if (!result) {
IanBenzMaxim 7:9cd16581b578 688 DS2476::GpioControl gpioControl(page);
IanBenzMaxim 7:9cd16581b578 689 if (!gpioControl.pioaConducting()) {
IanBenzMaxim 7:9cd16581b578 690 gpioControl.setPioaConducting(true);
IanBenzMaxim 7:9cd16581b578 691 result = ds2476.writeMemory(DS2476::gpioControlPage, page);
IanBenzMaxim 7:9cd16581b578 692 }
IanBenzMaxim 7:9cd16581b578 693 }
IanBenzMaxim 7:9cd16581b578 694 return result;
IanBenzMaxim 7:9cd16581b578 695 }
IanBenzMaxim 7:9cd16581b578 696
IanBenzMaxim 7:9cd16581b578 697 error_code enableRomId(DS2476 & ds2476) {
IanBenzMaxim 7:9cd16581b578 698 DS2476::Page::array page;
IanBenzMaxim 7:9cd16581b578 699 error_code result = ds2476.readMemory(DS2476::romOptionsPage, page);
IanBenzMaxim 7:9cd16581b578 700 if (!result) {
IanBenzMaxim 7:9cd16581b578 701 DS2476::RomOptions romOptions(page);
IanBenzMaxim 7:9cd16581b578 702 if (!romOptions.romBlockDisable()) {
IanBenzMaxim 7:9cd16581b578 703 romOptions.setRomBlockDisable(true);
IanBenzMaxim 7:9cd16581b578 704 result = ds2476.writeMemory(DS2476::romOptionsPage, page);
IanBenzMaxim 7:9cd16581b578 705 }
IanBenzMaxim 7:9cd16581b578 706 }
IanBenzMaxim 7:9cd16581b578 707 return result;
IanBenzMaxim 7:9cd16581b578 708 }
IanBenzMaxim 7:9cd16581b578 709
IanBenzMaxim 7:9cd16581b578 710 static void setAnonymous(RomId::span romId) {
IanBenzMaxim 7:9cd16581b578 711 std::fill(romId.begin(), romId.end(), 0xFF);
IanBenzMaxim 7:9cd16581b578 712 }
IanBenzMaxim 7:9cd16581b578 713
IanBenzMaxim 7:9cd16581b578 714 DS28C36::PageAuthenticationData &
IanBenzMaxim 7:9cd16581b578 715 DS28C36::PageAuthenticationData::setAnonymousRomId() {
IanBenzMaxim 7:9cd16581b578 716 setAnonymous(romId());
IanBenzMaxim 7:9cd16581b578 717 return *this;
IanBenzMaxim 7:9cd16581b578 718 }
IanBenzMaxim 7:9cd16581b578 719
IanBenzMaxim 7:9cd16581b578 720 DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() {
IanBenzMaxim 7:9cd16581b578 721 setAnonymous(romId());
IanBenzMaxim 7:9cd16581b578 722 return *this;
IanBenzMaxim 7:9cd16581b578 723 }
IanBenzMaxim 7:9cd16581b578 724
IanBenzMaxim 7:9cd16581b578 725 } // namespace MaximInterfaceDevices