boot.c revision 5c2c3b94617a29e9ada91649b5775a24fdc7c886
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, 0x0d, 0xA0, 28 0x00, 0x00, 0x04, 0x76, 0x50, 0x49, 29 0x58, 0x4C, 0x42, 0x4F, 0x4F, 0x54}; 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}; 41const uint8_t kLoadMetaClear[] = {0x80, 0x10, 0x00, 0x00}; 42const uint8_t kLoadMetaAppend[] = {0x80, 0x10, 0x01, 0x00}; 43static const uint16_t kMaxMetadataLoadSize = 1024; 44 45EseAppResult 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 60ESE_API void ese_boot_session_init(struct EseBootSession *session) { 61 session->ese = NULL; 62 session->active = false; 63 session->channel_id = 0; 64} 65 66ESE_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 137ESE_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 169ESE_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 230ESE_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 285EseAppResult 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 322EseAppResult 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 370ESE_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 448ESE_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 493ESE_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 552ESE_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 618ESE_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 669ESE_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 716ESE_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 756ESE_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