You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
6.7 KiB
206 lines
6.7 KiB
/*
|
|
* 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 <ese/ese.h>
|
|
#include <ese/log.h>
|
|
#include <ese/sysdeps.h>
|
|
|
|
#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_ */
|