1 /* Copyright 2020 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Kernel selection, loading, verification, and booting.
6 */
7
8 #include "2api.h"
9 #include "2common.h"
10 #include "2misc.h"
11 #include "2nvstorage.h"
12 #include "2rsa.h"
13 #include "2secdata.h"
14
vb2api_is_developer_signed(struct vb2_context * ctx)15 int vb2api_is_developer_signed(struct vb2_context *ctx)
16 {
17 struct vb2_shared_data *sd = vb2_get_sd(ctx);
18
19 if (!sd->kernel_key_offset || !sd->kernel_key_size) {
20 VB2_DEBUG("ERROR: Cannot call this before kernel_phase1!\n");
21 return 0;
22 }
23
24 struct vb2_public_key key;
25 if (vb2_unpack_key(&key, vb2_member_of(sd, sd->kernel_key_offset)))
26 return 0;
27
28 /* This is a debugging aid, not a security-relevant feature. There's no
29 reason to hardcode the whole key or waste time computing a hash. Just
30 spot check the starting bytes of the pseudorandom part of the key. */
31 uint32_t devkey_n0inv = ctx->flags & VB2_CONTEXT_RECOVERY_MODE ?
32 0x18cebcf5 : /* recovery_key.vbpubk @0x24 */
33 0xe0cd87d9; /* kernel_subkey.vbpubk @0x24 */
34
35 if (key.n0inv == devkey_n0inv)
36 return 1;
37
38 return 0;
39 }
40
41 test_mockable
vb2api_kernel_phase1(struct vb2_context * ctx)42 vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx)
43 {
44 struct vb2_shared_data *sd = vb2_get_sd(ctx);
45 struct vb2_workbuf wb;
46 struct vb2_packed_key *packed_key;
47 uint32_t flags;
48 vb2_error_t rv;
49
50 vb2_workbuf_from_ctx(ctx, &wb);
51
52 /*
53 * Init secdata_fwmp spaces. No need to init secdata_firmware or
54 * secdata_kernel, since they were already read during firmware
55 * verification. Ignore errors in recovery mode.
56 */
57 rv = vb2_secdata_fwmp_init(ctx);
58 if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
59 VB2_DEBUG("TPM: init secdata_fwmp returned %#x\n", rv);
60 vb2api_fail(ctx, VB2_RECOVERY_SECDATA_FWMP_INIT, rv);
61 return rv;
62 }
63
64 /* Initialize experimental feature flags while in normal RW path. */
65 if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
66 flags = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS);
67 flags &= ~VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED;
68 flags |= VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED;
69 vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, flags);
70 }
71
72 /* Read kernel version from secdata. */
73 sd->kernel_version_secdata =
74 vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
75
76 vb2_fill_dev_boot_flags(ctx);
77
78 /* Find the key to use to verify the kernel keyblock */
79 if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
80 /* Load recovery key from GBB. */
81 rv = vb2_gbb_read_recovery_key(ctx, &packed_key, NULL, &wb);
82 if (rv) {
83 if (ctx->boot_mode != VB2_BOOT_MODE_BROKEN_SCREEN)
84 VB2_DIE("GBB read recovery key failed.\n");
85 else
86 /*
87 * If we're headed for the BROKEN screen,
88 * we won't need the recovery key. Just
89 * short-circuit with success.
90 */
91 return VB2_SUCCESS;
92 }
93 } else {
94 /* Kernel subkey from firmware preamble */
95 struct vb2_fw_preamble *pre;
96
97 /* Make sure we have a firmware preamble loaded */
98 if (!sd->preamble_size)
99 return VB2_ERROR_API_KPHASE1_PREAMBLE;
100
101 pre = (struct vb2_fw_preamble *)
102 vb2_member_of(sd, sd->preamble_offset);
103 packed_key = &pre->kernel_subkey;
104 }
105
106 sd->kernel_key_offset = vb2_offset_of(sd, packed_key);
107 sd->kernel_key_size = packed_key->key_offset + packed_key->key_size;
108
109 vb2_set_workbuf_used(ctx, vb2_offset_of(sd, wb.buf));
110
111 if (vb2api_is_developer_signed(ctx))
112 VB2_DEBUG("This is developer-signed firmware.\n");
113
114 return VB2_SUCCESS;
115 }
116
handle_battery_cutoff(struct vb2_context * ctx)117 static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
118 {
119 /*
120 * Check if we need to cut-off battery. This should be done after EC
121 * FW and auxfw are updated, and before the kernel is started. This
122 * is to make sure all firmware is up-to-date before shipping (which
123 * is the typical use-case for cutoff).
124 */
125 if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
126 VB2_DEBUG("Request to cut-off battery\n");
127 vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
128
129 /* May lose power immediately, so commit our update now. */
130 VB2_TRY(vb2ex_commit_data(ctx));
131
132 vb2ex_ec_battery_cutoff();
133 return VB2_REQUEST_SHUTDOWN;
134 }
135
136 return VB2_SUCCESS;
137 }
138
vb2api_kernel_phase2(struct vb2_context * ctx)139 vb2_error_t vb2api_kernel_phase2(struct vb2_context *ctx)
140 {
141 struct vb2_shared_data *sd = vb2_get_sd(ctx);
142 vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
143
144 VB2_DEBUG("GBB flags are %#x\n", gbb_flags);
145
146 /*
147 * Do EC and auxfw software sync unless we're in recovery mode. This
148 * has UI but it's just a single non-interactive WAIT screen.
149 */
150 if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
151 VB2_TRY(vb2api_ec_sync(ctx));
152 VB2_TRY(vb2api_auxfw_sync(ctx));
153 VB2_TRY(handle_battery_cutoff(ctx));
154 }
155
156 /*
157 * If in the broken screen, save the recovery reason as subcode.
158 * Otherwise, clear any leftover recovery requests or subcodes.
159 */
160 vb2api_clear_recovery(ctx);
161
162 /*
163 * Clear the diagnostic request flag and commit nvdata to prevent
164 * booting back into diagnostic mode when a forced system reset occurs.
165 */
166 if (vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
167 vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
168 /*
169 * According to current FAFT design (firmware_MiniDiag), we
170 * need an AP reset after MiniDiag test items to preserve the
171 * CBMEM console logs. So we need to commit nvdata immediately
172 * to prevent booting back to VB2_BOOT_MODE_DIAGNOSTICS.
173 */
174 vb2ex_commit_data(ctx);
175 }
176
177 /* Select boot path */
178 switch (ctx->boot_mode) {
179 case VB2_BOOT_MODE_MANUAL_RECOVERY:
180 case VB2_BOOT_MODE_BROKEN_SCREEN:
181 /* If we're in recovery mode just to do memory retraining, all
182 we need to do is reboot. */
183 if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
184 VB2_DEBUG("Reboot after retraining in recovery\n");
185 return VB2_REQUEST_REBOOT;
186 }
187
188 /*
189 * Need to commit nvdata changes immediately, since we will be
190 * entering either manual recovery UI or BROKEN screen shortly.
191 */
192 vb2ex_commit_data(ctx);
193 break;
194 case VB2_BOOT_MODE_DIAGNOSTICS:
195 case VB2_BOOT_MODE_DEVELOPER:
196 break;
197 case VB2_BOOT_MODE_NORMAL:
198 if (vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST)) {
199 vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 0);
200 VB2_DEBUG("Normal mode: "
201 "reboot to unset display request\n");
202 return VB2_REQUEST_REBOOT;
203 }
204 break;
205 default:
206 return VB2_ERROR_ESCAPE_NO_BOOT;
207 }
208
209 return VB2_SUCCESS;
210 }
211
update_kernel_version(struct vb2_context * ctx)212 static void update_kernel_version(struct vb2_context *ctx)
213 {
214 struct vb2_shared_data *sd = vb2_get_sd(ctx);
215 uint32_t max_rollforward =
216 vb2_nv_get(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD);
217
218 VB2_DEBUG("Checking if TPM kernel version needs advancing\n");
219
220 /*
221 * Special case for when we're trying a slot with new firmware.
222 * Firmware updates also usually change the kernel key, which means
223 * that the new firmware can only boot a new kernel, and the old
224 * firmware in the previous slot can only boot the previous kernel.
225 *
226 * Don't roll-forward the kernel version, because we don't yet know if
227 * the new kernel will successfully boot.
228 */
229 if (vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_TRYING) {
230 VB2_DEBUG("Trying new FW; "
231 "skip kernel version roll-forward.\n");
232 return;
233 }
234
235 /*
236 * Limit kernel version rollforward if needed. Can't limit kernel
237 * version to less than the version currently in the TPM. That is,
238 * we're limiting rollforward, not allowing rollback.
239 */
240 uint32_t original_kernel_version =
241 vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
242
243 if (max_rollforward < original_kernel_version)
244 max_rollforward = original_kernel_version;
245
246 if (sd->kernel_version_secdata > max_rollforward) {
247 VB2_DEBUG("Limiting TPM kernel version roll-forward "
248 "to %#x < %#x\n",
249 max_rollforward, sd->kernel_version_secdata);
250
251 sd->kernel_version_secdata = max_rollforward;
252 }
253
254 if (sd->kernel_version_secdata > original_kernel_version) {
255 vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS,
256 sd->kernel_version_secdata);
257 } else {
258 sd->kernel_version_secdata = original_kernel_version;
259 }
260 }
261
vb2api_kernel_finalize(struct vb2_context * ctx)262 vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx)
263 {
264 vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
265
266 /*
267 * Disallow booting to kernel when NO_BOOT flag is set, except when
268 * GBB flag disables software sync.
269 */
270 if (!(gbb_flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
271 && (ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED)
272 && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
273 VB2_DEBUG("Blocking escape from NO_BOOT mode.\n");
274 vb2api_fail(ctx, VB2_RECOVERY_ESCAPE_NO_BOOT, 0);
275 return VB2_ERROR_ESCAPE_NO_BOOT;
276 }
277
278 if (ctx->boot_mode == VB2_BOOT_MODE_NORMAL)
279 update_kernel_version(ctx);
280
281 return VB2_SUCCESS;
282 }
283