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