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