/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * See the README.md in the parent (../../..) directory. */ #ifndef ESE_APP_BOOT_H_ #define ESE_APP_BOOT_H_ 1 #include "../../../../../libese/include/ese/ese.h" #include "../../../../../libese/include/ese/log.h" #include "../../../../../libese-sysdeps/include/ese/sysdeps.h" #include "../../../../include/ese/app/result.h" #ifdef __cplusplus extern "C" { #endif /** * EseBootSession carries the necessary start for interfacing * with the methods below. * * Its usage follows a lifecycle like: * * EseAppResult res; * EseBootSession session; * ese_boot_session_init(&session); * res = ese_boot_session_open(ese, &session); * if (res != ESE_APP_RESULT_OK) { * ... handle error (especially cooldown) ... * } * ... ese_boot_* ... * ese_boot_session_close(&session); * */ struct EseBootSession { struct EseInterface *ese; bool active; uint8_t channel_id; }; /** * The Storage applet supports up to 8 64-bit storage slots for storing * rollback protection indices. */ const uint8_t kEseBootRollbackSlotCount = 8; /** * When using the LOCK_OWNER, a key, or other relevant value, must be supplied. * It may be at most OWNER_LOCK_METADATA_SIZE as defined in * card/src/com/android/verifiedboot/storage/Storage.java. */ const uint16_t kEseBootOwnerKeyMax = 2048; /* Keep in sync with card/src/com/android/verifiedboot/storage/Storage.java */ /** * This enum reflects the types of Locks that are supported by * the ese_boot_lock_* calls. */ typedef enum { kEseBootLockIdCarrier = 0, kEseBootLockIdDevice, kEseBootLockIdBoot, kEseBootLockIdOwner, kEseBootLockIdMax = kEseBootLockIdOwner, } EseBootLockId; /** * Initializes a pre-allocated |session| for use. */ void ese_boot_session_init(struct EseBootSession *session); /** * Configures a communication session with the Storage applet using a logical * channel on an already open |ese| object. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_session_open(struct EseInterface *ese, struct EseBootSession *session); /** * Shuts down the logical channel with the Storage applet and invalidates * the |session| internal state. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_session_close(struct EseBootSession *session); /** * Retrieves the uint8_t value stored for the lock specified by |lockId|. * On success, the value is stored in |lockVal|. If the byte is 0x0, then * the lock is cleared (or unlocked). If it is any non-zero value, then it * is locked. Any specific byte value may have additional meaning to the * caller. * * @returns ESE_APP_RESULT_OK if |lockVal| contains a valid byte. */ EseAppResult ese_boot_lock_get(struct EseBootSession *session, EseBootLockId lockId, uint8_t *lockVal); /** * Retrieves extended lock data for the lock specified by |lockId|. * * |maxSize| specifies how many bytes may be written to |lockData|. |dataLen| * will be updated to hold the length of the data received from the applet on * success. * * The first byte of |lockData| will be the lock's value. The remaining bytes * are the associated metadata. See the README.md for more details * on each lock's behavior. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_lock_xget( struct EseBootSession *session, EseBootLockId lockId, uint8_t *lockData, uint16_t maxSize, uint16_t *dataLen); /** * Sets the lock specified by |lockId| to |lockVal|. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_lock_set(struct EseBootSession *session, EseBootLockId lockId, uint8_t lockVal); /** * Sets the lock and its metadata specified by |lockId| and |lockData|, * respectively. |dataLen| indicates the length of |lockData|. * * The first byte of |lockData| will be treated as the new value for the lock. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_lock_xset(struct EseBootSession *session, EseBootLockId lockId, const uint8_t *lockData, uint16_t dataLen); /** * Performs a test of the carrier unlock code by allowing the caller to specify * a fake internal nonce value, fake internal device data, as well as an actual * unlock token (made up of a nonce and signature). * * @returns ESE_APP_RESULT_OK on success. On failure, it is worthwhile to * check the upper two bytes in the result code if the lower two bytes * are ESE_APP_RESULT_ERROR_APPLET as it will provide an error * specific to the code path. These applet codes are not (yet) * considered API and should be relied on for debugging. */ EseAppResult ese_boot_carrier_lock_test(struct EseBootSession *session, const uint8_t *testdata, uint16_t len); /** * Transitions the applet from "factory" mode to "production" mode. * This can only be done if the bootloader gpio has not been cleared. * * When not in production mode, the applet will ignore the bootloader gpio * and allow for all the locks to be provisioned. Once |mode| is set * to true, LOCK_CARRIER can not be "lock"ed once cleared and any locks * that depend on being in the bootloader (gpio not cleared) will respect * that value. */ EseAppResult ese_boot_set_production(struct EseBootSession *session, bool production_mode); /** * Debugging helper that emits the internal value of production, bootloader gpio, * and lock initialization and storage. It is not insecure in the field, but * it is not expected to be needed during normal operation. */ EseAppResult ese_boot_get_state(struct EseBootSession *session, uint8_t *state, uint16_t maxSize); /** * Stores |value| in the specified |slot| in the applet. * * @returns ESE_APP_RESULT_OK on success */ EseAppResult ese_boot_rollback_index_write(struct EseBootSession *session, uint8_t slot, uint64_t value); /** * Reads a uint64_t from |slot| into |value|. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_rollback_index_read(struct EseBootSession *session, uint8_t slot, uint64_t *value); /** * Resets all lock state -- including internal metadata. * This should only be called in factory or under test. * * @returns ESE_APP_RESULT_OK on success. */ EseAppResult ese_boot_reset_locks(struct EseBootSession *session); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* ESE_APP_BOOT_H_ */