Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Committer:
IanBenzMaxim
Date:
Mon Nov 06 14:39:18 2017 -0600
Revision:
0:f77ad7f72d04
Child:
3:f818ea5172ed
Initial commit.

Who changed what in which revision?

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