Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Committer:
reARMnimator
Date:
Mon Jan 06 15:54:55 2020 +0000
Revision:
10:de4b8812877d
Parent:
7:471901a04573
Fixed inappropriate include path.

Who changed what in which revision?

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