1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Support SPI communication with NXP PN553/PN80T secure element.
17 */
18
19 #include "include/ese/hw/nxp/pn80t/common.h"
20
nxp_pn80t_preprocess(const struct Teq1ProtocolOptions * const opts,struct Teq1Frame * frame,int tx)21 int nxp_pn80t_preprocess(const struct Teq1ProtocolOptions *const opts,
22 struct Teq1Frame *frame, int tx) {
23 if (tx) {
24 /* Recompute the LRC with the NAD of 0x00 */
25 frame->header.NAD = 0x00;
26 frame->INF[frame->header.LEN] = teq1_compute_LRC(frame);
27 frame->header.NAD = opts->node_address;
28 ALOGV("interface is preprocessing outbound frame");
29 } else {
30 /* Replace the NAD with 0x00 so the LRC check passes. */
31 ALOGV("interface is preprocessing inbound frame (%x->%x)",
32 frame->header.NAD, 0x00);
33 if (frame->header.NAD != opts->host_address) {
34 ALOGV("Rewriting from unknown NAD: %x", frame->header.NAD);
35 }
36 frame->header.NAD = 0x00;
37 ALOGV("Frame length: %x", frame->header.LEN);
38 }
39 return 0;
40 }
41
42 static const struct Teq1ProtocolOptions kTeq1Options = {
43 .host_address = 0xA5,
44 .node_address = 0x5A,
45 .bwt = 1.624f, /* cwt by default would be ~8k * 1.05s */
46 /* 1.05ms is the vendor defined ETU. However, we use this
47 * for polling and 7 * etu (7ms) is a long time to wait
48 * between poll attempts so we divided by 7. */
49 .etu = 0.00015f, /* elementary time unit, in seconds */
50 .preprocess = &nxp_pn80t_preprocess,
51 };
52
nxp_pn80t_open(struct EseInterface * ese,void * board)53 int nxp_pn80t_open(struct EseInterface *ese, void *board) {
54 struct NxpState *ns;
55 const struct Pn80tPlatform *platform;
56 _static_assert(sizeof(ese->pad) >= sizeof(struct NxpState *),
57 "Pad size too small to use NXP HW");
58 platform = ese->ops->opts;
59
60 /* Ensure all required functions exist */
61 if (!platform->initialize || !platform->release || !platform->toggle_reset ||
62 !platform->wait) {
63 ALOGE("Required functions not implemented in supplied platform");
64 ese_set_error(ese, kNxpPn80tErrorPlatformInit);
65 return -1;
66 }
67
68 ns = NXP_PN80T_STATE(ese);
69 TEQ1_INIT_CARD_STATE((struct Teq1CardState *)(&ese->pad[0]));
70 ns->handle = platform->initialize(board);
71 if (!ns->handle) {
72 ALOGE("platform initialization failed");
73 ese_set_error(ese, kNxpPn80tErrorPlatformInit);
74 return -1;
75 }
76 /* Toggle all required power GPIOs.
77 * Each platform may prefer to handle the power
78 * muxing specific. E.g., if NFC is in use, it would
79 * be unwise to unset VEN. However, the implementation
80 * here will attempt it if supported.
81 */
82 if (platform->toggle_ven) {
83 platform->toggle_ven(ns->handle, 1);
84 }
85 if (platform->toggle_power_req) {
86 platform->toggle_power_req(ns->handle, 1);
87 }
88 /* Power on eSE */
89 platform->toggle_reset(ns->handle, 1);
90 return 0;
91 }
92
93 /* Used for soft-reset when possible. */
94 uint32_t nxp_pn80t_send_cooldown(struct EseInterface *ese, bool end);
95
nxp_pn80t_reset(struct EseInterface * ese)96 int nxp_pn80t_reset(struct EseInterface *ese) {
97 const struct Pn80tPlatform *platform = ese->ops->opts;
98 struct NxpState *ns = NXP_PN80T_STATE(ese);
99
100 /* If there is no error, perform a soft reset.
101 * If there is no cooldown time associated, go ahead and do a real
102 * reset as there is no other interface to trigger a hard reset.
103 *
104 * This avoids pulling the power when a cooldown is in progress
105 * if it is at all possible to avoid.
106 */
107 if (!ese_error(ese)) {
108 const uint32_t cooldownSec = nxp_pn80t_send_cooldown(ese, false);
109 if (!ese_error(ese) && cooldownSec > 0) {
110 return 0;
111 }
112 }
113
114 if (platform->toggle_reset(ns->handle, 0) < 0) {
115 ese_set_error(ese, kNxpPn80tErrorResetToggle);
116 return -1;
117 }
118 if (platform->toggle_reset(ns->handle, 1) < 0) {
119 ese_set_error(ese, kNxpPn80tErrorResetToggle);
120 return -1;
121 }
122
123 /* Start fresh with the reset. */
124 ese->error.is_err = false;
125 return 0;
126 }
127
nxp_pn80t_poll(struct EseInterface * ese,uint8_t poll_for,float timeout,int complete)128 int nxp_pn80t_poll(struct EseInterface *ese, uint8_t poll_for, float timeout,
129 int complete) {
130 struct NxpState *ns = NXP_PN80T_STATE(ese);
131 const struct Pn80tPlatform *platform = ese->ops->opts;
132 /* Attempt to read a 8-bit character once per 8-bit character transmission
133 * window (in seconds).
134 */
135 int intervals = (int)(0.5f + timeout / (7.0f * kTeq1Options.etu));
136 uint8_t byte = 0xff;
137 ALOGV("interface polling for start of frame/host node address: %x", poll_for);
138 /* If we had interrupts, we could just get notified by the driver. */
139 do {
140 /*
141 * In practice, if complete=true, then no transmission
142 * should attempt again until after 1000usec.
143 */
144 if (ese->ops->hw_receive(ese, &byte, 1, complete) != 1) {
145 ALOGE("failed to read one byte");
146 ese_set_error(ese, kNxpPn80tErrorPollRead);
147 return -1;
148 }
149 if (byte == poll_for) {
150 ALOGV("Polled for byte seen: %x with %d intervals remaining.", poll_for,
151 intervals);
152 ALOGV("RX[0]: %.2X", byte);
153 return 1;
154 } else {
155 ALOGV("No match (saw %x)", byte);
156 }
157 platform->wait(ns->handle,
158 7.0f * kTeq1Options.etu * 1000000.0f); /* s -> us */
159 ALOGV("poll interval %d: no match.", intervals);
160 } while (intervals-- > 0);
161 ALOGW("polling timed out.");
162 return -1;
163 }
164
165 /* Returns the seconds the chip has requested to stay powered for internal
166 * maintenance. This is not expected during normal operation, but it is still
167 * a possible operating response.
168 *
169 * There are three timers reserved for internal state usage which are
170 * not reliable API. As such, this function returns the maximum time
171 * in seconds that the chip would like to stay powered-on.
172 */
173 #define SECURE_TIMER 0xF1
174 #define ATTACK_COUNTER 0xF2
175 #define RESTRICTED_MODE_PENALTY 0xF3
nxp_pn80t_send_cooldown(struct EseInterface * ese,bool end)176 uint32_t nxp_pn80t_send_cooldown(struct EseInterface *ese, bool end) {
177 struct NxpState *ns = NXP_PN80T_STATE(ese);
178 const struct Pn80tPlatform *platform = ese->ops->opts;
179 const static uint8_t kEndofApduSession[] = {0x5a, 0xc5, 0x00, 0xc5};
180 const static uint8_t kResetSession[] = {0x5a, 0xc4, 0x00, 0xc4};
181 const uint8_t *const message = end ? kEndofApduSession : kResetSession;
182 const uint32_t message_len =
183 end ? sizeof(kEndofApduSession) : sizeof(kResetSession);
184
185 if (ese_error(ese)) {
186 return 0;
187 }
188
189 ese->ops->hw_transmit(ese, message, message_len, 1);
190 if (ese_error(ese)) {
191 ALOGE("failed to transmit cooldown check");
192 return 0;
193 }
194
195 nxp_pn80t_poll(ese, kTeq1Options.host_address, 5.0f, 0);
196 if (ese_error(ese)) {
197 ALOGE("failed to poll during cooldown");
198 return 0;
199 }
200 uint8_t rx_buf[32];
201 const uint32_t bytes_read =
202 ese->ops->hw_receive(ese, rx_buf, sizeof(rx_buf), 1);
203 if (ese_error(ese)) {
204 ALOGE("failed to receive cooldown response");
205 return 0;
206 }
207
208 ALOGI("Requested power-down delay times (sec):");
209 /* For each tag type, walk the response to extract the value. */
210 uint32_t max_wait = 0;
211 if (bytes_read >= 0x8 && rx_buf[0] == 0xe5 && rx_buf[1] == 0x12) {
212 uint8_t *tag_ptr = &rx_buf[2];
213 while (tag_ptr < (rx_buf + bytes_read)) {
214 const uint8_t tag = *tag_ptr;
215 const uint8_t length = *(tag_ptr + 1);
216
217 /* The cooldown timers are 32-bit values. */
218 if (length == sizeof(uint32_t)) {
219 const uint32_t *const value_ptr = (uint32_t *)(tag_ptr + 2);
220 uint32_t cooldown = ese_be32toh(*value_ptr);
221 switch (tag) {
222 case RESTRICTED_MODE_PENALTY:
223 /* This timer is in minutes, so convert it to seconds. */
224 cooldown *= 60;
225 /* Fallthrough */
226 case SECURE_TIMER:
227 case ATTACK_COUNTER:
228 ALOGI("- Timer 0x%.2X: %d", tag, cooldown);
229 if (cooldown > max_wait) {
230 max_wait = cooldown;
231 /* Wait 25ms Guard time to make sure eSE is in DPD mode */
232 platform->wait(ns->handle, 25000);
233 }
234 break;
235 default:
236 /* Ignore -- not a known tag. */
237 break;
238 }
239 }
240 tag_ptr += 2 + length;
241 }
242 }
243 return max_wait;
244 }
245
nxp_pn80t_handle_interface_call(struct EseInterface * ese,const struct EseSgBuffer * tx_buf,uint32_t tx_len,struct EseSgBuffer * rx_buf,uint32_t rx_len)246 uint32_t nxp_pn80t_handle_interface_call(struct EseInterface *ese,
247 const struct EseSgBuffer *tx_buf,
248 uint32_t tx_len,
249 struct EseSgBuffer *rx_buf,
250 uint32_t rx_len) {
251 /* Catch proprietary, host-targeted calls FF XX 00 00 */
252 const struct Pn80tPlatform *platform = ese->ops->opts;
253 static const uint32_t kCommandLength = 4;
254 static const uint8_t kResetCommand = 0x01;
255 static const uint8_t kGpioToggleCommand = 0xe0;
256 static const uint8_t kCooldownCommand = 0xe1;
257 uint8_t buf[kCommandLength + 1];
258 uint8_t ok[2] = {0x90, 0x00};
259 struct NxpState *ns = NXP_PN80T_STATE(ese);
260 /* Over-copy by one to make sure the command length matches. */
261 if (ese_sg_to_buf(tx_buf, tx_len, 0, sizeof(buf), buf) != kCommandLength) {
262 return 0;
263 }
264 /* Let 3 change as an argument. */
265 if (buf[0] != 0xff || buf[2] != 0x00) {
266 return 0;
267 }
268 switch (buf[1]) {
269 case kResetCommand:
270 ALOGI("interface command received: reset");
271 /* Force a hard reset by setting an error on the hw. */
272 ese_set_error(ese, 0);
273 if (nxp_pn80t_reset(ese) < 0) {
274 /* Warning, state unchanged error. */
275 ok[0] = 0x62;
276 }
277 return ese_sg_from_buf(rx_buf, rx_len, 0, sizeof(ok), ok);
278 case kGpioToggleCommand:
279 ALOGI("interface command received: gpio toggle");
280 if (platform->toggle_bootloader) {
281 int ret = platform->toggle_bootloader(ns->handle, buf[3]);
282 if (ret) {
283 /* Grab the bottom two bytes. */
284 ok[0] = (ret >> 8) & 0xff;
285 ok[1] = ret & 0xff;
286 }
287 } else {
288 /* Not found. */
289 ok[0] = 0x6a;
290 ok[1] = 0x82;
291 }
292 return ese_sg_from_buf(rx_buf, rx_len, 0, sizeof(ok), ok);
293 case kCooldownCommand:
294 ALOGI("interface command received: cooldown");
295 uint8_t reply[6] = {0, 0, 0, 0, 0x90, 0x00};
296 const uint32_t cooldownSec = nxp_pn80t_send_cooldown(ese, false);
297 *(uint32_t *)(&reply[0]) = ese_htole32(cooldownSec);
298 if (ese_error(ese)) {
299 /* Return SW_UKNOWN on an ese failure. */
300 reply[sizeof(reply) - 2] = 0x6f;
301 }
302 return ese_sg_from_buf(rx_buf, rx_len, 0, sizeof(reply), reply);
303 }
304 return 0;
305 }
306
nxp_pn80t_transceive(struct EseInterface * ese,const struct EseSgBuffer * tx_buf,uint32_t tx_len,struct EseSgBuffer * rx_buf,uint32_t rx_len)307 uint32_t nxp_pn80t_transceive(struct EseInterface *ese,
308 const struct EseSgBuffer *tx_buf, uint32_t tx_len,
309 struct EseSgBuffer *rx_buf, uint32_t rx_len) {
310
311 const uint32_t recvd =
312 nxp_pn80t_handle_interface_call(ese, tx_buf, tx_len, rx_buf, rx_len);
313 if (recvd > 0) {
314 return recvd;
315 }
316 return teq1_transceive(ese, &kTeq1Options, tx_buf, tx_len, rx_buf, rx_len);
317 }
318
nxp_pn80t_close(struct EseInterface * ese)319 void nxp_pn80t_close(struct EseInterface *ese) {
320 ALOGV("%s: called", __func__);
321 struct NxpState *ns = NXP_PN80T_STATE(ese);
322 const struct Pn80tPlatform *platform = ese->ops->opts;
323 const uint32_t wait_sec = nxp_pn80t_send_cooldown(ese, true);
324
325 /* After the cooldown, the device should go to sleep.
326 * If not post-use time is required, power down to ensure
327 * that the device is powered down when the OS is not on.
328 */
329 if (ese_error(ese) || wait_sec == 0) {
330 platform->toggle_reset(ns->handle, 0);
331 if (platform->toggle_power_req) {
332 platform->toggle_power_req(ns->handle, 0);
333 }
334 if (platform->toggle_ven) {
335 platform->toggle_ven(ns->handle, 0);
336 }
337 }
338
339 platform->release(ns->handle);
340 ns->handle = NULL;
341 }
342
343 const char *kNxpPn80tErrorMessages[] = {
344 /* The first three are required by teq1_transceive use. */
345 TEQ1_ERROR_MESSAGES,
346 /* The rest are pn80t impl specific. */
347 [kNxpPn80tErrorPlatformInit] = "unable to initialize platform",
348 [kNxpPn80tErrorPollRead] = "failed to read one byte",
349 [kNxpPn80tErrorReceive] = "failed to read",
350 [kNxpPn80tErrorReceiveSize] = "attempted to receive too much data",
351 [kNxpPn80tErrorTransmitSize] = "attempted to transfer too much data",
352 [kNxpPn80tErrorTransmit] = "failed to transmit",
353 [kNxpPn80tErrorResetToggle] = "failed to toggle reset",
354 };
355