Extended MaximInterface
Dependents: mbed_DS28EC20_GPIO
Devices/DS28C36_DS2476.cpp@7:471901a04573, 2019-03-04 (annotated)
- Committer:
- IanBenzMaxim
- Date:
- Mon Mar 04 08:10:00 2019 -0600
- Revision:
- 7:471901a04573
- Parent:
- 6:a8c83a2e6fa4
Updated to version 1.7.
Who changed what in which revision?
User | Revision | Line number | New 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(¶meter, 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(¶meter, 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(¶meter, 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(¶meter, 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 |