aboutsummaryrefslogtreecommitdiff
path: root/apps/boot/include/ese/app/boot.h
blob: 48714faa0a372de3c860ca54b108bac9be99fba4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
 * 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_ */