1*5c4dab75SAndroid Build Coastguard Worker /*
2*5c4dab75SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*5c4dab75SAndroid Build Coastguard Worker *
4*5c4dab75SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*5c4dab75SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*5c4dab75SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*5c4dab75SAndroid Build Coastguard Worker *
8*5c4dab75SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*5c4dab75SAndroid Build Coastguard Worker *
10*5c4dab75SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*5c4dab75SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*5c4dab75SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5c4dab75SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*5c4dab75SAndroid Build Coastguard Worker * limitations under the License.
15*5c4dab75SAndroid Build Coastguard Worker */
16*5c4dab75SAndroid Build Coastguard Worker
17*5c4dab75SAndroid Build Coastguard Worker #include "include/ese/app/boot.h"
18*5c4dab75SAndroid Build Coastguard Worker #include "boot_private.h"
19*5c4dab75SAndroid Build Coastguard Worker
20*5c4dab75SAndroid Build Coastguard Worker const uint8_t kBootStateVersion = 0x1;
21*5c4dab75SAndroid Build Coastguard Worker const uint16_t kBootStorageLength = 4096;
22*5c4dab75SAndroid Build Coastguard Worker /* Non-static, but visibility=hidden so they can be used in test. */
23*5c4dab75SAndroid Build Coastguard Worker const uint8_t kManageChannelOpen[] = {0x00, 0x70, 0x00, 0x00, 0x01};
24*5c4dab75SAndroid Build Coastguard Worker const uint32_t kManageChannelOpenLength = (uint32_t)sizeof(kManageChannelOpen);
25*5c4dab75SAndroid Build Coastguard Worker const uint8_t kManageChannelClose[] = {0x00, 0x70, 0x80, 0x00, 0x00};
26*5c4dab75SAndroid Build Coastguard Worker
27*5c4dab75SAndroid Build Coastguard Worker const uint8_t kSelectApplet[] = {0x00, 0xA4, 0x04, 0x00, 0x0d, 0xA0,
28*5c4dab75SAndroid Build Coastguard Worker 0x00, 0x00, 0x04, 0x76, 0x50, 0x49,
29*5c4dab75SAndroid Build Coastguard Worker 0x58, 0x4C, 0x42, 0x4F, 0x4F, 0x54};
30*5c4dab75SAndroid Build Coastguard Worker const uint32_t kSelectAppletLength = (uint32_t)sizeof(kSelectApplet);
31*5c4dab75SAndroid Build Coastguard Worker // Supported commands.
32*5c4dab75SAndroid Build Coastguard Worker const uint8_t kGetState[] = {0x80, 0x00, 0x00, 0x00, 0x00};
33*5c4dab75SAndroid Build Coastguard Worker const uint8_t kLoadCmd[] = {0x80, 0x02};
34*5c4dab75SAndroid Build Coastguard Worker const uint8_t kStoreCmd[] = {0x80, 0x04};
35*5c4dab75SAndroid Build Coastguard Worker const uint8_t kGetLockState[] = {0x80, 0x06, 0x00, 0x00, 0x00};
36*5c4dab75SAndroid Build Coastguard Worker const uint8_t kSetLockState[] = {0x80, 0x08, 0x00, 0x00, 0x00};
37*5c4dab75SAndroid Build Coastguard Worker const uint8_t kSetProduction[] = {0x80, 0x0a};
38*5c4dab75SAndroid Build Coastguard Worker const uint8_t kCarrierLockTest[] = {0x80, 0x0c, 0x00, 0x00};
39*5c4dab75SAndroid Build Coastguard Worker const uint8_t kFactoryReset[] = {0x80, 0x0e, 0x00, 0x00};
40*5c4dab75SAndroid Build Coastguard Worker const uint8_t kLockReset[] = {0x80, 0x0e, 0x01, 0x00};
41*5c4dab75SAndroid Build Coastguard Worker const uint8_t kLoadMetaClear[] = {0x80, 0x10, 0x00, 0x00};
42*5c4dab75SAndroid Build Coastguard Worker const uint8_t kLoadMetaAppend[] = {0x80, 0x10, 0x01, 0x00};
43*5c4dab75SAndroid Build Coastguard Worker static const uint16_t kMaxMetadataLoadSize = 1024;
44*5c4dab75SAndroid Build Coastguard Worker
check_apdu_status(uint8_t code[2])45*5c4dab75SAndroid Build Coastguard Worker EseAppResult check_apdu_status(uint8_t code[2]) {
46*5c4dab75SAndroid Build Coastguard Worker if (code[0] == 0x90 && code[1] == 0x00) {
47*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
48*5c4dab75SAndroid Build Coastguard Worker }
49*5c4dab75SAndroid Build Coastguard Worker if (code[0] == 0x66 && code[1] == 0xA5) {
50*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COOLDOWN;
51*5c4dab75SAndroid Build Coastguard Worker }
52*5c4dab75SAndroid Build Coastguard Worker if (code[0] == 0x6A && code[1] == 0x83) {
53*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_UNCONFIGURED;
54*5c4dab75SAndroid Build Coastguard Worker }
55*5c4dab75SAndroid Build Coastguard Worker /* TODO(wad) Bubble up the error code if needed. */
56*5c4dab75SAndroid Build Coastguard Worker ALOGE("unhandled response %.2x %.2x", code[0], code[1]);
57*5c4dab75SAndroid Build Coastguard Worker return ese_make_os_result(code[0], code[1]);
58*5c4dab75SAndroid Build Coastguard Worker }
59*5c4dab75SAndroid Build Coastguard Worker
ese_boot_session_init(struct EseBootSession * session)60*5c4dab75SAndroid Build Coastguard Worker ESE_API void ese_boot_session_init(struct EseBootSession *session) {
61*5c4dab75SAndroid Build Coastguard Worker session->ese = NULL;
62*5c4dab75SAndroid Build Coastguard Worker session->active = false;
63*5c4dab75SAndroid Build Coastguard Worker session->channel_id = 0;
64*5c4dab75SAndroid Build Coastguard Worker }
65*5c4dab75SAndroid Build Coastguard Worker
ese_boot_session_open(struct EseInterface * ese,struct EseBootSession * session)66*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_session_open(struct EseInterface *ese,
67*5c4dab75SAndroid Build Coastguard Worker struct EseBootSession *session) {
68*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[2];
69*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx;
70*5c4dab75SAndroid Build Coastguard Worker uint8_t rx_buf[32];
71*5c4dab75SAndroid Build Coastguard Worker int rx_len;
72*5c4dab75SAndroid Build Coastguard Worker if (!ese || !session) {
73*5c4dab75SAndroid Build Coastguard Worker ALOGE("Invalid |ese| or |session|");
74*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
75*5c4dab75SAndroid Build Coastguard Worker }
76*5c4dab75SAndroid Build Coastguard Worker if (session->active == true) {
77*5c4dab75SAndroid Build Coastguard Worker ALOGE("|session| is already active");
78*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
79*5c4dab75SAndroid Build Coastguard Worker }
80*5c4dab75SAndroid Build Coastguard Worker /* Instantiate a logical channel */
81*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive(ese, kManageChannelOpen, sizeof(kManageChannelOpen),
82*5c4dab75SAndroid Build Coastguard Worker rx_buf, sizeof(rx_buf));
83*5c4dab75SAndroid Build Coastguard Worker if (ese_error(ese)) {
84*5c4dab75SAndroid Build Coastguard Worker ALOGE("transceive error: code:%d message:'%s'", ese_error_code(ese),
85*5c4dab75SAndroid Build Coastguard Worker ese_error_message(ese));
86*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
87*5c4dab75SAndroid Build Coastguard Worker }
88*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 0) {
89*5c4dab75SAndroid Build Coastguard Worker ALOGE("transceive error: rx_len: %d", rx_len);
90*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
91*5c4dab75SAndroid Build Coastguard Worker }
92*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2) {
93*5c4dab75SAndroid Build Coastguard Worker ALOGE("transceive error: reply too short");
94*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
95*5c4dab75SAndroid Build Coastguard Worker }
96*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret;
97*5c4dab75SAndroid Build Coastguard Worker ret = check_apdu_status(&rx_buf[rx_len - 2]);
98*5c4dab75SAndroid Build Coastguard Worker if (ret != ESE_APP_RESULT_OK) {
99*5c4dab75SAndroid Build Coastguard Worker ALOGE("MANAGE CHANNEL OPEN failed with error code: %x %x",
100*5c4dab75SAndroid Build Coastguard Worker rx_buf[rx_len - 2], rx_buf[rx_len - 1]);
101*5c4dab75SAndroid Build Coastguard Worker return ret;
102*5c4dab75SAndroid Build Coastguard Worker }
103*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 3) {
104*5c4dab75SAndroid Build Coastguard Worker ALOGE("transceive error: successful reply unexpectedly short");
105*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
106*5c4dab75SAndroid Build Coastguard Worker }
107*5c4dab75SAndroid Build Coastguard Worker session->ese = ese;
108*5c4dab75SAndroid Build Coastguard Worker session->channel_id = rx_buf[rx_len - 3];
109*5c4dab75SAndroid Build Coastguard Worker
110*5c4dab75SAndroid Build Coastguard Worker /* Select Boot Applet. */
111*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kSelectApplet[0] | session->channel_id;
112*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
113*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
114*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kSelectApplet[1];
115*5c4dab75SAndroid Build Coastguard Worker tx[1].len = sizeof(kSelectApplet) - 1;
116*5c4dab75SAndroid Build Coastguard Worker rx.base = &rx_buf[0];
117*5c4dab75SAndroid Build Coastguard Worker rx.len = sizeof(rx_buf);
118*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(ese, tx, 2, &rx, 1);
119*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 0 || ese_error(ese)) {
120*5c4dab75SAndroid Build Coastguard Worker ALOGE("transceive error: caller should check ese_error()");
121*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
122*5c4dab75SAndroid Build Coastguard Worker }
123*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2) {
124*5c4dab75SAndroid Build Coastguard Worker ALOGE("transceive error: reply too short");
125*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
126*5c4dab75SAndroid Build Coastguard Worker }
127*5c4dab75SAndroid Build Coastguard Worker ret = check_apdu_status(&rx_buf[rx_len - 2]);
128*5c4dab75SAndroid Build Coastguard Worker if (ret != ESE_APP_RESULT_OK) {
129*5c4dab75SAndroid Build Coastguard Worker ALOGE("SELECT failed with error code: %x %x", rx_buf[rx_len - 2],
130*5c4dab75SAndroid Build Coastguard Worker rx_buf[rx_len - 1]);
131*5c4dab75SAndroid Build Coastguard Worker return ret;
132*5c4dab75SAndroid Build Coastguard Worker }
133*5c4dab75SAndroid Build Coastguard Worker session->active = true;
134*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
135*5c4dab75SAndroid Build Coastguard Worker }
136*5c4dab75SAndroid Build Coastguard Worker
ese_boot_session_close(struct EseBootSession * session)137*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_session_close(struct EseBootSession *session) {
138*5c4dab75SAndroid Build Coastguard Worker uint8_t rx_buf[32];
139*5c4dab75SAndroid Build Coastguard Worker int rx_len;
140*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese) {
141*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
142*5c4dab75SAndroid Build Coastguard Worker }
143*5c4dab75SAndroid Build Coastguard Worker if (!session->active || session->channel_id == 0) {
144*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
145*5c4dab75SAndroid Build Coastguard Worker }
146*5c4dab75SAndroid Build Coastguard Worker /* Release the channel */
147*5c4dab75SAndroid Build Coastguard Worker uint8_t close_channel[sizeof(kManageChannelClose)];
148*5c4dab75SAndroid Build Coastguard Worker ese_memcpy(close_channel, kManageChannelClose, sizeof(kManageChannelClose));
149*5c4dab75SAndroid Build Coastguard Worker close_channel[0] |= session->channel_id;
150*5c4dab75SAndroid Build Coastguard Worker close_channel[3] |= session->channel_id;
151*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive(session->ese, close_channel, sizeof(close_channel),
152*5c4dab75SAndroid Build Coastguard Worker rx_buf, sizeof(rx_buf));
153*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 0 || ese_error(session->ese)) {
154*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
155*5c4dab75SAndroid Build Coastguard Worker }
156*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2) {
157*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
158*5c4dab75SAndroid Build Coastguard Worker }
159*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret;
160*5c4dab75SAndroid Build Coastguard Worker ret = check_apdu_status(&rx_buf[rx_len - 2]);
161*5c4dab75SAndroid Build Coastguard Worker if (ret != ESE_APP_RESULT_OK) {
162*5c4dab75SAndroid Build Coastguard Worker return ret;
163*5c4dab75SAndroid Build Coastguard Worker }
164*5c4dab75SAndroid Build Coastguard Worker session->channel_id = 0;
165*5c4dab75SAndroid Build Coastguard Worker session->active = false;
166*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
167*5c4dab75SAndroid Build Coastguard Worker }
168*5c4dab75SAndroid Build Coastguard Worker
ese_boot_lock_xget(struct EseBootSession * session,EseBootLockId lock,uint8_t * lockData,uint16_t maxSize,uint16_t * length)169*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_lock_xget(struct EseBootSession *session,
170*5c4dab75SAndroid Build Coastguard Worker EseBootLockId lock, uint8_t *lockData,
171*5c4dab75SAndroid Build Coastguard Worker uint16_t maxSize, uint16_t *length) {
172*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[4];
173*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[3];
174*5c4dab75SAndroid Build Coastguard Worker int rx_len;
175*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
176*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
177*5c4dab75SAndroid Build Coastguard Worker }
178*5c4dab75SAndroid Build Coastguard Worker if (lock > kEseBootLockIdMax) {
179*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
180*5c4dab75SAndroid Build Coastguard Worker }
181*5c4dab75SAndroid Build Coastguard Worker if (maxSize < 1 || maxSize > 4096) {
182*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
183*5c4dab75SAndroid Build Coastguard Worker }
184*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kGetLockState[0] | session->channel_id;
185*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
186*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
187*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kGetLockState[1];
188*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
189*5c4dab75SAndroid Build Coastguard Worker
190*5c4dab75SAndroid Build Coastguard Worker uint8_t p1p2[] = {lock, 0x01};
191*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &p1p2[0];
192*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
193*5c4dab75SAndroid Build Coastguard Worker
194*5c4dab75SAndroid Build Coastguard Worker // Accomodate the applet 2 byte status code.
195*5c4dab75SAndroid Build Coastguard Worker uint8_t max_reply[] = {0x0, ((maxSize + 2) >> 8), ((maxSize + 2) & 0xff)};
196*5c4dab75SAndroid Build Coastguard Worker tx[3].base = &max_reply[0];
197*5c4dab75SAndroid Build Coastguard Worker tx[3].len = sizeof(max_reply);
198*5c4dab75SAndroid Build Coastguard Worker
199*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[2]; // App reply or APDU error.
200*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
201*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
202*5c4dab75SAndroid Build Coastguard Worker // Applet data
203*5c4dab75SAndroid Build Coastguard Worker rx[1].base = lockData;
204*5c4dab75SAndroid Build Coastguard Worker rx[1].len = maxSize;
205*5c4dab75SAndroid Build Coastguard Worker // Only used if the full maxSize is used.
206*5c4dab75SAndroid Build Coastguard Worker uint8_t apdu_status[2];
207*5c4dab75SAndroid Build Coastguard Worker rx[2].base = &apdu_status[0];
208*5c4dab75SAndroid Build Coastguard Worker rx[2].len = sizeof(apdu_status);
209*5c4dab75SAndroid Build Coastguard Worker
210*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 4, rx, 3);
211*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
212*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xget: failed to read lock state (%d)", lock);
213*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
214*5c4dab75SAndroid Build Coastguard Worker }
215*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 2) {
216*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xget: SE exception");
217*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[0]);
218*5c4dab75SAndroid Build Coastguard Worker return ret;
219*5c4dab75SAndroid Build Coastguard Worker }
220*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the aplet status and the completion code.
221*5c4dab75SAndroid Build Coastguard Worker *length = (uint16_t)(rx_len - 4);
222*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 4) {
223*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xget: received applet error code %x %x", lockData[0],
224*5c4dab75SAndroid Build Coastguard Worker lockData[1]);
225*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(lockData[0], lockData[1]);
226*5c4dab75SAndroid Build Coastguard Worker }
227*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
228*5c4dab75SAndroid Build Coastguard Worker }
229*5c4dab75SAndroid Build Coastguard Worker
ese_boot_lock_get(struct EseBootSession * session,EseBootLockId lock,uint8_t * lockVal)230*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_lock_get(struct EseBootSession *session,
231*5c4dab75SAndroid Build Coastguard Worker EseBootLockId lock, uint8_t *lockVal) {
232*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[3];
233*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
234*5c4dab75SAndroid Build Coastguard Worker int rx_len;
235*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
236*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
237*5c4dab75SAndroid Build Coastguard Worker }
238*5c4dab75SAndroid Build Coastguard Worker if (lock > kEseBootLockIdMax) {
239*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
240*5c4dab75SAndroid Build Coastguard Worker }
241*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kGetLockState[0] | session->channel_id;
242*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
243*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
244*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kGetLockState[1];
245*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
246*5c4dab75SAndroid Build Coastguard Worker
247*5c4dab75SAndroid Build Coastguard Worker uint8_t p1p2[] = {lock, 0x0};
248*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &p1p2[0];
249*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
250*5c4dab75SAndroid Build Coastguard Worker
251*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[6];
252*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
253*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
254*5c4dab75SAndroid Build Coastguard Worker
255*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 3, rx, 1);
256*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
257*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_get: failed to read lock state (%d).", lock);
258*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
259*5c4dab75SAndroid Build Coastguard Worker }
260*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[rx_len - 2]);
261*5c4dab75SAndroid Build Coastguard Worker if (ret != ESE_APP_RESULT_OK) {
262*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_get: SE OS error.");
263*5c4dab75SAndroid Build Coastguard Worker return ret;
264*5c4dab75SAndroid Build Coastguard Worker }
265*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 5) {
266*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_get: communication error");
267*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
268*5c4dab75SAndroid Build Coastguard Worker }
269*5c4dab75SAndroid Build Coastguard Worker // TODO: unify in the applet, then map them here.
270*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 && reply[1] != 0x0) {
271*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_get: Applet error: %x %x", reply[0], reply[1]);
272*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
273*5c4dab75SAndroid Build Coastguard Worker }
274*5c4dab75SAndroid Build Coastguard Worker if (lockVal) {
275*5c4dab75SAndroid Build Coastguard Worker *lockVal = reply[2];
276*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
277*5c4dab75SAndroid Build Coastguard Worker }
278*5c4dab75SAndroid Build Coastguard Worker
279*5c4dab75SAndroid Build Coastguard Worker if (reply[2] != 0) {
280*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_TRUE;
281*5c4dab75SAndroid Build Coastguard Worker }
282*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_FALSE;
283*5c4dab75SAndroid Build Coastguard Worker }
284*5c4dab75SAndroid Build Coastguard Worker
ese_boot_meta_clear(struct EseBootSession * session)285*5c4dab75SAndroid Build Coastguard Worker EseAppResult ese_boot_meta_clear(struct EseBootSession *session) {
286*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[2];
287*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
288*5c4dab75SAndroid Build Coastguard Worker int rx_len;
289*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
290*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
291*5c4dab75SAndroid Build Coastguard Worker }
292*5c4dab75SAndroid Build Coastguard Worker
293*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kLoadMetaClear[0] | session->channel_id;
294*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
295*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
296*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kLoadMetaClear[1];
297*5c4dab75SAndroid Build Coastguard Worker tx[1].len = sizeof(kLoadMetaClear) - 1;
298*5c4dab75SAndroid Build Coastguard Worker
299*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
300*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
301*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
302*5c4dab75SAndroid Build Coastguard Worker
303*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 2, rx, 1);
304*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
305*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_clear: communication failure");
306*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
307*5c4dab75SAndroid Build Coastguard Worker }
308*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the applet status and the completion code.
309*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 4) {
310*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_clear: SE exception");
311*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[rx_len - 2]);
312*5c4dab75SAndroid Build Coastguard Worker return ret;
313*5c4dab75SAndroid Build Coastguard Worker }
314*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
315*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_clear: received applet error code %.2x %.2x", reply[0],
316*5c4dab75SAndroid Build Coastguard Worker reply[1]);
317*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
318*5c4dab75SAndroid Build Coastguard Worker }
319*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
320*5c4dab75SAndroid Build Coastguard Worker }
321*5c4dab75SAndroid Build Coastguard Worker
ese_boot_meta_append(struct EseBootSession * session,const uint8_t * data,uint16_t dataLen)322*5c4dab75SAndroid Build Coastguard Worker EseAppResult ese_boot_meta_append(struct EseBootSession *session,
323*5c4dab75SAndroid Build Coastguard Worker const uint8_t *data, uint16_t dataLen) {
324*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[4];
325*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
326*5c4dab75SAndroid Build Coastguard Worker int rx_len;
327*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
328*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
329*5c4dab75SAndroid Build Coastguard Worker }
330*5c4dab75SAndroid Build Coastguard Worker if (dataLen > kMaxMetadataLoadSize) {
331*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_append: too much data provided");
332*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
333*5c4dab75SAndroid Build Coastguard Worker }
334*5c4dab75SAndroid Build Coastguard Worker
335*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kLoadMetaAppend[0] | session->channel_id;
336*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
337*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
338*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kLoadMetaAppend[1];
339*5c4dab75SAndroid Build Coastguard Worker tx[1].len = sizeof(kLoadMetaAppend) - 1;
340*5c4dab75SAndroid Build Coastguard Worker
341*5c4dab75SAndroid Build Coastguard Worker uint8_t apdu_len[] = {0x0, (dataLen >> 8), (dataLen & 0xff)};
342*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &apdu_len[0];
343*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(apdu_len);
344*5c4dab75SAndroid Build Coastguard Worker tx[3].c_base = data;
345*5c4dab75SAndroid Build Coastguard Worker tx[3].len = dataLen;
346*5c4dab75SAndroid Build Coastguard Worker
347*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
348*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
349*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
350*5c4dab75SAndroid Build Coastguard Worker
351*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 4, rx, 1);
352*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
353*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_append: communication failure");
354*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
355*5c4dab75SAndroid Build Coastguard Worker }
356*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the applet status and the completion code.
357*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 4) {
358*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_append: SE exception");
359*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[rx_len - 2]);
360*5c4dab75SAndroid Build Coastguard Worker return ret;
361*5c4dab75SAndroid Build Coastguard Worker }
362*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
363*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_meta_append: received applet error code %.2x %.2x",
364*5c4dab75SAndroid Build Coastguard Worker reply[0], reply[1]);
365*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
366*5c4dab75SAndroid Build Coastguard Worker }
367*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
368*5c4dab75SAndroid Build Coastguard Worker }
369*5c4dab75SAndroid Build Coastguard Worker
ese_boot_lock_xset(struct EseBootSession * session,EseBootLockId lockId,const uint8_t * lockData,uint16_t dataLen)370*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_lock_xset(struct EseBootSession *session,
371*5c4dab75SAndroid Build Coastguard Worker EseBootLockId lockId,
372*5c4dab75SAndroid Build Coastguard Worker const uint8_t *lockData,
373*5c4dab75SAndroid Build Coastguard Worker uint16_t dataLen) {
374*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[3];
375*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
376*5c4dab75SAndroid Build Coastguard Worker int rx_len;
377*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
378*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
379*5c4dab75SAndroid Build Coastguard Worker }
380*5c4dab75SAndroid Build Coastguard Worker if (lockId > kEseBootLockIdMax) {
381*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
382*5c4dab75SAndroid Build Coastguard Worker }
383*5c4dab75SAndroid Build Coastguard Worker if (dataLen < 1 || dataLen > kEseBootOwnerKeyMax + 1) {
384*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: too much data: %hu > %d", dataLen,
385*5c4dab75SAndroid Build Coastguard Worker kEseBootOwnerKeyMax + 1);
386*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
387*5c4dab75SAndroid Build Coastguard Worker }
388*5c4dab75SAndroid Build Coastguard Worker
389*5c4dab75SAndroid Build Coastguard Worker // Locks with metadata require a multi-step upload to meet the
390*5c4dab75SAndroid Build Coastguard Worker // constraints of the transport.
391*5c4dab75SAndroid Build Coastguard Worker EseAppResult res = ese_boot_meta_clear(session);
392*5c4dab75SAndroid Build Coastguard Worker if (res != ESE_APP_RESULT_OK) {
393*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: unable to clear scratch metadata");
394*5c4dab75SAndroid Build Coastguard Worker return res;
395*5c4dab75SAndroid Build Coastguard Worker }
396*5c4dab75SAndroid Build Coastguard Worker // The first byte is the lock value itself, so we skip it.
397*5c4dab75SAndroid Build Coastguard Worker const uint8_t *cursor = &lockData[1];
398*5c4dab75SAndroid Build Coastguard Worker uint16_t remaining = dataLen - 1;
399*5c4dab75SAndroid Build Coastguard Worker while (remaining > 0) {
400*5c4dab75SAndroid Build Coastguard Worker uint16_t chunk = (512 < remaining) ? 512 : remaining;
401*5c4dab75SAndroid Build Coastguard Worker res = ese_boot_meta_append(session, cursor, chunk);
402*5c4dab75SAndroid Build Coastguard Worker ALOGI("ese_boot_lock_xset: sending chunk %x", remaining);
403*5c4dab75SAndroid Build Coastguard Worker if (res != ESE_APP_RESULT_OK) {
404*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: unable to upload metadata");
405*5c4dab75SAndroid Build Coastguard Worker return res;
406*5c4dab75SAndroid Build Coastguard Worker }
407*5c4dab75SAndroid Build Coastguard Worker remaining -= chunk;
408*5c4dab75SAndroid Build Coastguard Worker cursor += chunk;
409*5c4dab75SAndroid Build Coastguard Worker }
410*5c4dab75SAndroid Build Coastguard Worker
411*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kSetLockState[0] | session->channel_id;
412*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
413*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
414*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kSetLockState[1];
415*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
416*5c4dab75SAndroid Build Coastguard Worker
417*5c4dab75SAndroid Build Coastguard Worker uint8_t lockIdLockValueUseMeta[] = {lockId, lockData[0], 0x1, 0x1};
418*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &lockIdLockValueUseMeta[0];
419*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(lockIdLockValueUseMeta);
420*5c4dab75SAndroid Build Coastguard Worker
421*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
422*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
423*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
424*5c4dab75SAndroid Build Coastguard Worker
425*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 3, rx, 1);
426*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
427*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: failed to set lock state (%d).", lockId);
428*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
429*5c4dab75SAndroid Build Coastguard Worker }
430*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 2) {
431*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: SE exception");
432*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[0]);
433*5c4dab75SAndroid Build Coastguard Worker return ret;
434*5c4dab75SAndroid Build Coastguard Worker }
435*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the applet status and the completion code.
436*5c4dab75SAndroid Build Coastguard Worker if (rx_len != 4) {
437*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: communication error");
438*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
439*5c4dab75SAndroid Build Coastguard Worker }
440*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
441*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_xset: received applet error code %x %x", reply[0],
442*5c4dab75SAndroid Build Coastguard Worker reply[1]);
443*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
444*5c4dab75SAndroid Build Coastguard Worker }
445*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
446*5c4dab75SAndroid Build Coastguard Worker }
447*5c4dab75SAndroid Build Coastguard Worker
ese_boot_lock_set(struct EseBootSession * session,EseBootLockId lockId,uint8_t lockValue)448*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_lock_set(struct EseBootSession *session,
449*5c4dab75SAndroid Build Coastguard Worker EseBootLockId lockId,
450*5c4dab75SAndroid Build Coastguard Worker uint8_t lockValue) {
451*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[3];
452*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
453*5c4dab75SAndroid Build Coastguard Worker int rx_len;
454*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
455*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
456*5c4dab75SAndroid Build Coastguard Worker }
457*5c4dab75SAndroid Build Coastguard Worker if (lockId > kEseBootLockIdMax) {
458*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
459*5c4dab75SAndroid Build Coastguard Worker }
460*5c4dab75SAndroid Build Coastguard Worker
461*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kSetLockState[0] | session->channel_id;
462*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
463*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
464*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kSetLockState[1];
465*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
466*5c4dab75SAndroid Build Coastguard Worker
467*5c4dab75SAndroid Build Coastguard Worker uint8_t lockIdLockValueNoMeta[] = {lockId, lockValue, 0x1, 0x0};
468*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &lockIdLockValueNoMeta[0];
469*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(lockIdLockValueNoMeta);
470*5c4dab75SAndroid Build Coastguard Worker
471*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
472*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
473*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
474*5c4dab75SAndroid Build Coastguard Worker
475*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 3, rx, 1);
476*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
477*5c4dab75SAndroid Build Coastguard Worker ALOGE("Failed to set lock state (%d).", lockId);
478*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
479*5c4dab75SAndroid Build Coastguard Worker }
480*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the applet status and the completion code.
481*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 4) {
482*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_lock_set: SE exception");
483*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[rx_len - 2]);
484*5c4dab75SAndroid Build Coastguard Worker return ret;
485*5c4dab75SAndroid Build Coastguard Worker }
486*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
487*5c4dab75SAndroid Build Coastguard Worker ALOGE("Received applet error code %x %x", reply[0], reply[1]);
488*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
489*5c4dab75SAndroid Build Coastguard Worker }
490*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
491*5c4dab75SAndroid Build Coastguard Worker }
492*5c4dab75SAndroid Build Coastguard Worker
ese_boot_rollback_index_write(struct EseBootSession * session,uint8_t slot,uint64_t value)493*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_rollback_index_write(
494*5c4dab75SAndroid Build Coastguard Worker struct EseBootSession *session, uint8_t slot, uint64_t value) {
495*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[5];
496*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
497*5c4dab75SAndroid Build Coastguard Worker uint8_t chan;
498*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
499*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: invalid session");
500*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
501*5c4dab75SAndroid Build Coastguard Worker }
502*5c4dab75SAndroid Build Coastguard Worker if (slot >= kEseBootRollbackSlotCount) {
503*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: slot invalid");
504*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
505*5c4dab75SAndroid Build Coastguard Worker }
506*5c4dab75SAndroid Build Coastguard Worker
507*5c4dab75SAndroid Build Coastguard Worker // APDU CLA
508*5c4dab75SAndroid Build Coastguard Worker chan = kStoreCmd[0] | session->channel_id;
509*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
510*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
511*5c4dab75SAndroid Build Coastguard Worker // APDU INS
512*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kStoreCmd[1];
513*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
514*5c4dab75SAndroid Build Coastguard Worker // APDU P1 - P2
515*5c4dab75SAndroid Build Coastguard Worker const uint8_t p1p2[] = {slot, 0x0};
516*5c4dab75SAndroid Build Coastguard Worker tx[2].c_base = &p1p2[0];
517*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
518*5c4dab75SAndroid Build Coastguard Worker // APDU Lc
519*5c4dab75SAndroid Build Coastguard Worker uint8_t len = (uint8_t)sizeof(value);
520*5c4dab75SAndroid Build Coastguard Worker tx[3].base = &len;
521*5c4dab75SAndroid Build Coastguard Worker tx[3].len = sizeof(len);
522*5c4dab75SAndroid Build Coastguard Worker // APDU data
523*5c4dab75SAndroid Build Coastguard Worker tx[4].base = (uint8_t *)&value;
524*5c4dab75SAndroid Build Coastguard Worker tx[4].len = sizeof(value);
525*5c4dab75SAndroid Build Coastguard Worker
526*5c4dab75SAndroid Build Coastguard Worker uint8_t rx_buf[4];
527*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &rx_buf[0];
528*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(rx_buf);
529*5c4dab75SAndroid Build Coastguard Worker
530*5c4dab75SAndroid Build Coastguard Worker int rx_len = ese_transceive_sg(session->ese, tx, 5, rx, 1);
531*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 0 || ese_error(session->ese)) {
532*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: comm error");
533*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
534*5c4dab75SAndroid Build Coastguard Worker }
535*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2) {
536*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: too few bytes recieved.");
537*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
538*5c4dab75SAndroid Build Coastguard Worker }
539*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 4) {
540*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: APDU Error");
541*5c4dab75SAndroid Build Coastguard Worker return check_apdu_status(&rx_buf[rx_len - 2]);
542*5c4dab75SAndroid Build Coastguard Worker }
543*5c4dab75SAndroid Build Coastguard Worker
544*5c4dab75SAndroid Build Coastguard Worker if (rx_buf[0] != 0 || rx_buf[1] != 0) {
545*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: applet error code %x %x", rx_buf[0],
546*5c4dab75SAndroid Build Coastguard Worker rx_buf[1]);
547*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(rx_buf[0], rx_buf[1]);
548*5c4dab75SAndroid Build Coastguard Worker }
549*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
550*5c4dab75SAndroid Build Coastguard Worker }
551*5c4dab75SAndroid Build Coastguard Worker
ese_boot_rollback_index_read(struct EseBootSession * session,uint8_t slot,uint64_t * value)552*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_rollback_index_read(
553*5c4dab75SAndroid Build Coastguard Worker struct EseBootSession *session, uint8_t slot, uint64_t *value) {
554*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[4];
555*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
556*5c4dab75SAndroid Build Coastguard Worker uint8_t chan;
557*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
558*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: invalid session");
559*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
560*5c4dab75SAndroid Build Coastguard Worker }
561*5c4dab75SAndroid Build Coastguard Worker if (!value) {
562*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: NULL value supplied");
563*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
564*5c4dab75SAndroid Build Coastguard Worker }
565*5c4dab75SAndroid Build Coastguard Worker if (slot >= kEseBootRollbackSlotCount) {
566*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_write: slot invalid");
567*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
568*5c4dab75SAndroid Build Coastguard Worker }
569*5c4dab75SAndroid Build Coastguard Worker
570*5c4dab75SAndroid Build Coastguard Worker // APDU CLA
571*5c4dab75SAndroid Build Coastguard Worker chan = kLoadCmd[0] | session->channel_id;
572*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
573*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
574*5c4dab75SAndroid Build Coastguard Worker // APDU INS
575*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kLoadCmd[1];
576*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
577*5c4dab75SAndroid Build Coastguard Worker // APDU P1 - P2
578*5c4dab75SAndroid Build Coastguard Worker const uint8_t p1p2[] = {slot, 0x0};
579*5c4dab75SAndroid Build Coastguard Worker tx[2].c_base = &p1p2[0];
580*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
581*5c4dab75SAndroid Build Coastguard Worker // APDU Lc
582*5c4dab75SAndroid Build Coastguard Worker uint8_t len = 0;
583*5c4dab75SAndroid Build Coastguard Worker tx[3].base = &len;
584*5c4dab75SAndroid Build Coastguard Worker tx[3].len = sizeof(len);
585*5c4dab75SAndroid Build Coastguard Worker
586*5c4dab75SAndroid Build Coastguard Worker uint8_t rx_buf[4 + sizeof(*value)];
587*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &rx_buf[0];
588*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(rx_buf);
589*5c4dab75SAndroid Build Coastguard Worker
590*5c4dab75SAndroid Build Coastguard Worker int rx_len = ese_transceive_sg(session->ese, tx, 4, rx, 1);
591*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 0 || ese_error(session->ese)) {
592*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_read: comm error");
593*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
594*5c4dab75SAndroid Build Coastguard Worker }
595*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2) {
596*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_read: too few bytes recieved.");
597*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
598*5c4dab75SAndroid Build Coastguard Worker }
599*5c4dab75SAndroid Build Coastguard Worker // TODO(wad) We should check the APDU status anyway.
600*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 4) {
601*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_read: APDU Error");
602*5c4dab75SAndroid Build Coastguard Worker return check_apdu_status(&rx_buf[rx_len - 2]);
603*5c4dab75SAndroid Build Coastguard Worker }
604*5c4dab75SAndroid Build Coastguard Worker if (rx_buf[0] != 0 || rx_buf[1] != 0) {
605*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_read: applet error code %x %x", rx_buf[0],
606*5c4dab75SAndroid Build Coastguard Worker rx_buf[1]);
607*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(rx_buf[0], rx_buf[1]);
608*5c4dab75SAndroid Build Coastguard Worker }
609*5c4dab75SAndroid Build Coastguard Worker if (rx_len != (int)sizeof(rx_buf)) {
610*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_rollback_index_read: unexpected partial reply (%d)",
611*5c4dab75SAndroid Build Coastguard Worker rx_len);
612*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
613*5c4dab75SAndroid Build Coastguard Worker }
614*5c4dab75SAndroid Build Coastguard Worker *value = *((uint64_t *)&rx_buf[2]);
615*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
616*5c4dab75SAndroid Build Coastguard Worker }
617*5c4dab75SAndroid Build Coastguard Worker
ese_boot_carrier_lock_test(struct EseBootSession * session,const uint8_t * testdata,uint16_t len)618*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_carrier_lock_test(struct EseBootSession *session,
619*5c4dab75SAndroid Build Coastguard Worker const uint8_t *testdata,
620*5c4dab75SAndroid Build Coastguard Worker uint16_t len) {
621*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[5];
622*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
623*5c4dab75SAndroid Build Coastguard Worker int rx_len;
624*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
625*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
626*5c4dab75SAndroid Build Coastguard Worker }
627*5c4dab75SAndroid Build Coastguard Worker if (len > 2048) {
628*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
629*5c4dab75SAndroid Build Coastguard Worker }
630*5c4dab75SAndroid Build Coastguard Worker
631*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kCarrierLockTest[0] | session->channel_id;
632*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
633*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
634*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kCarrierLockTest[1];
635*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
636*5c4dab75SAndroid Build Coastguard Worker
637*5c4dab75SAndroid Build Coastguard Worker uint8_t p1p2[] = {0, 0};
638*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &p1p2[0];
639*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
640*5c4dab75SAndroid Build Coastguard Worker
641*5c4dab75SAndroid Build Coastguard Worker uint8_t apdu_len[] = {0x0, (len >> 8), (len & 0xff)};
642*5c4dab75SAndroid Build Coastguard Worker tx[3].base = &apdu_len[0];
643*5c4dab75SAndroid Build Coastguard Worker tx[3].len = sizeof(apdu_len);
644*5c4dab75SAndroid Build Coastguard Worker
645*5c4dab75SAndroid Build Coastguard Worker tx[4].c_base = testdata;
646*5c4dab75SAndroid Build Coastguard Worker tx[4].len = len;
647*5c4dab75SAndroid Build Coastguard Worker
648*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
649*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
650*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
651*5c4dab75SAndroid Build Coastguard Worker
652*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 5, rx, 1);
653*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
654*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_carrier_lock_test: failed to test carrier vector");
655*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
656*5c4dab75SAndroid Build Coastguard Worker }
657*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 4) {
658*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_carrier_lock_test: SE exception");
659*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[rx_len - 2]);
660*5c4dab75SAndroid Build Coastguard Worker return ret;
661*5c4dab75SAndroid Build Coastguard Worker }
662*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
663*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_carrier_lock_test: applet error %x %x", reply[0], reply[1]);
664*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
665*5c4dab75SAndroid Build Coastguard Worker }
666*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
667*5c4dab75SAndroid Build Coastguard Worker }
668*5c4dab75SAndroid Build Coastguard Worker
ese_boot_set_production(struct EseBootSession * session,bool production_mode)669*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_set_production(struct EseBootSession *session,
670*5c4dab75SAndroid Build Coastguard Worker bool production_mode) {
671*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[3];
672*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
673*5c4dab75SAndroid Build Coastguard Worker int rx_len;
674*5c4dab75SAndroid Build Coastguard Worker uint8_t prodVal = production_mode ? 0x1 : 0x00;
675*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
676*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
677*5c4dab75SAndroid Build Coastguard Worker }
678*5c4dab75SAndroid Build Coastguard Worker
679*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kSetProduction[0] | session->channel_id;
680*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
681*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
682*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kSetProduction[1];
683*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
684*5c4dab75SAndroid Build Coastguard Worker
685*5c4dab75SAndroid Build Coastguard Worker uint8_t p1p2[] = {prodVal, 0x0};
686*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &p1p2[0];
687*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
688*5c4dab75SAndroid Build Coastguard Worker
689*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
690*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
691*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
692*5c4dab75SAndroid Build Coastguard Worker
693*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 3, rx, 1);
694*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
695*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_set_production: comms failure.");
696*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
697*5c4dab75SAndroid Build Coastguard Worker }
698*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 2) {
699*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_set_production: SE exception");
700*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[0]);
701*5c4dab75SAndroid Build Coastguard Worker return ret;
702*5c4dab75SAndroid Build Coastguard Worker }
703*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the aplet status and the completion code.
704*5c4dab75SAndroid Build Coastguard Worker if (rx_len != 4) {
705*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_set_production: not enough data (%d)", rx_len);
706*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
707*5c4dab75SAndroid Build Coastguard Worker }
708*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
709*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_set_production: applet error code %x %x", reply[0],
710*5c4dab75SAndroid Build Coastguard Worker reply[1]);
711*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
712*5c4dab75SAndroid Build Coastguard Worker }
713*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
714*5c4dab75SAndroid Build Coastguard Worker }
715*5c4dab75SAndroid Build Coastguard Worker
ese_boot_reset_locks(struct EseBootSession * session)716*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_reset_locks(struct EseBootSession *session) {
717*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[2];
718*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[1];
719*5c4dab75SAndroid Build Coastguard Worker int rx_len;
720*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
721*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
722*5c4dab75SAndroid Build Coastguard Worker }
723*5c4dab75SAndroid Build Coastguard Worker
724*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kLockReset[0] | session->channel_id;
725*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
726*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
727*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kLockReset[1];
728*5c4dab75SAndroid Build Coastguard Worker tx[1].len = sizeof(kLockReset) - 1;
729*5c4dab75SAndroid Build Coastguard Worker
730*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[4]; // App reply or APDU error.
731*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
732*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
733*5c4dab75SAndroid Build Coastguard Worker
734*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 2, rx, 1);
735*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
736*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_reset_locks: comms failure.");
737*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
738*5c4dab75SAndroid Build Coastguard Worker }
739*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 2) {
740*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_reset_locks: SE exception");
741*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[0]);
742*5c4dab75SAndroid Build Coastguard Worker return ret;
743*5c4dab75SAndroid Build Coastguard Worker }
744*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the aplet status and the completion code.
745*5c4dab75SAndroid Build Coastguard Worker if (rx_len != 4) {
746*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_reset_locks: not enough data (%d)", rx_len);
747*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
748*5c4dab75SAndroid Build Coastguard Worker }
749*5c4dab75SAndroid Build Coastguard Worker if (reply[0] != 0x0 || reply[1] != 0x0) {
750*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_reset_locks: applet error code %x %x", reply[0], reply[1]);
751*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
752*5c4dab75SAndroid Build Coastguard Worker }
753*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
754*5c4dab75SAndroid Build Coastguard Worker }
755*5c4dab75SAndroid Build Coastguard Worker
ese_boot_get_state(struct EseBootSession * session,uint8_t * state,uint16_t maxSize)756*5c4dab75SAndroid Build Coastguard Worker ESE_API EseAppResult ese_boot_get_state(struct EseBootSession *session,
757*5c4dab75SAndroid Build Coastguard Worker uint8_t *state, uint16_t maxSize) {
758*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer tx[4];
759*5c4dab75SAndroid Build Coastguard Worker struct EseSgBuffer rx[3];
760*5c4dab75SAndroid Build Coastguard Worker int rx_len;
761*5c4dab75SAndroid Build Coastguard Worker if (!session || !session->ese || !session->active) {
762*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_ARGUMENTS;
763*5c4dab75SAndroid Build Coastguard Worker }
764*5c4dab75SAndroid Build Coastguard Worker uint8_t chan = kGetState[0] | session->channel_id;
765*5c4dab75SAndroid Build Coastguard Worker tx[0].base = &chan;
766*5c4dab75SAndroid Build Coastguard Worker tx[0].len = 1;
767*5c4dab75SAndroid Build Coastguard Worker tx[1].base = (uint8_t *)&kGetState[1];
768*5c4dab75SAndroid Build Coastguard Worker tx[1].len = 1;
769*5c4dab75SAndroid Build Coastguard Worker
770*5c4dab75SAndroid Build Coastguard Worker uint8_t p1p2[] = {0x0, 0x0};
771*5c4dab75SAndroid Build Coastguard Worker tx[2].base = &p1p2[0];
772*5c4dab75SAndroid Build Coastguard Worker tx[2].len = sizeof(p1p2);
773*5c4dab75SAndroid Build Coastguard Worker
774*5c4dab75SAndroid Build Coastguard Worker // Accomodate the applet 2 byte status code.
775*5c4dab75SAndroid Build Coastguard Worker uint8_t max_reply[] = {0x0, ((maxSize + 2) >> 8), ((maxSize + 2) & 0xff)};
776*5c4dab75SAndroid Build Coastguard Worker tx[3].base = &max_reply[0];
777*5c4dab75SAndroid Build Coastguard Worker tx[3].len = sizeof(max_reply);
778*5c4dab75SAndroid Build Coastguard Worker
779*5c4dab75SAndroid Build Coastguard Worker uint8_t reply[2]; // App reply or APDU error.
780*5c4dab75SAndroid Build Coastguard Worker rx[0].base = &reply[0];
781*5c4dab75SAndroid Build Coastguard Worker rx[0].len = sizeof(reply);
782*5c4dab75SAndroid Build Coastguard Worker // Applet data
783*5c4dab75SAndroid Build Coastguard Worker rx[1].base = state;
784*5c4dab75SAndroid Build Coastguard Worker rx[1].len = maxSize;
785*5c4dab75SAndroid Build Coastguard Worker // Just in case the maxSize is used. That is unlikely.
786*5c4dab75SAndroid Build Coastguard Worker // TODO(wad) clean this up.
787*5c4dab75SAndroid Build Coastguard Worker uint8_t apdu_status[2];
788*5c4dab75SAndroid Build Coastguard Worker rx[2].base = &apdu_status[0];
789*5c4dab75SAndroid Build Coastguard Worker rx[2].len = sizeof(apdu_status);
790*5c4dab75SAndroid Build Coastguard Worker
791*5c4dab75SAndroid Build Coastguard Worker rx_len = ese_transceive_sg(session->ese, tx, 4, rx, 3);
792*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 2 || ese_error(session->ese)) {
793*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_get_state: comm failure");
794*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_COMM_FAILED;
795*5c4dab75SAndroid Build Coastguard Worker }
796*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 2) {
797*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_get_state: SE exception");
798*5c4dab75SAndroid Build Coastguard Worker EseAppResult ret = check_apdu_status(&reply[0]);
799*5c4dab75SAndroid Build Coastguard Worker return ret;
800*5c4dab75SAndroid Build Coastguard Worker }
801*5c4dab75SAndroid Build Coastguard Worker // Expect the full payload plus the aplet status and the completion code.
802*5c4dab75SAndroid Build Coastguard Worker if (rx_len < 3 + 4) {
803*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_get_state: did not receive enough data: %d", rx_len);
804*5c4dab75SAndroid Build Coastguard Worker if (rx_len == 4) {
805*5c4dab75SAndroid Build Coastguard Worker ALOGE("Received applet error code %x %x", reply[0], reply[1]);
806*5c4dab75SAndroid Build Coastguard Worker }
807*5c4dab75SAndroid Build Coastguard Worker return ese_make_app_result(reply[0], reply[1]);
808*5c4dab75SAndroid Build Coastguard Worker }
809*5c4dab75SAndroid Build Coastguard Worker // Well known version (for now).
810*5c4dab75SAndroid Build Coastguard Worker if (state[0] == kBootStateVersion) {
811*5c4dab75SAndroid Build Coastguard Worker uint16_t expected = (state[1] << 8) | (state[2]);
812*5c4dab75SAndroid Build Coastguard Worker // Reduce for version (1), status (2).
813*5c4dab75SAndroid Build Coastguard Worker if ((rx_len - 3) != expected) {
814*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_get_state: may be truncated: %d != %d", rx_len - 5,
815*5c4dab75SAndroid Build Coastguard Worker expected);
816*5c4dab75SAndroid Build Coastguard Worker }
817*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_OK;
818*5c4dab75SAndroid Build Coastguard Worker }
819*5c4dab75SAndroid Build Coastguard Worker ALOGE("ese_boot_get_state: missing version tag");
820*5c4dab75SAndroid Build Coastguard Worker return ESE_APP_RESULT_ERROR_OS;
821*5c4dab75SAndroid Build Coastguard Worker }
822