180
return false;
181
}
182
183
+ if (!sclp_is_fac_ipl_flag_on(SCCB_FAC_IPL_SCLAF_BIT)) {
184
+ puts("Secure IPL Code Loading Attributes Facility is not supported by"
185
+ " the hypervisor!");
186
+ return false;
187
+ }
188
+
189
return true;
190
}
191
216
}
217
}
218
219
+static bool is_psw_valid(uint64_t psw, IplDeviceComponentEntry *comp)
220
+{
221
+ uint32_t addr = psw & 0x7fffffff;
222
+
223
+ /*
224
+ * PSW points within a signed binary code component
225
+ *
226
+ * Check addr falls within [comp->addr, comp->addr + comp->len - 2],
227
+ * ensuring at least 2 bytes (minimum instruction length) remain.
228
+ */
229
+ return intersects(addr, 1, comp->addr, comp->len - 1);
230
+}
231
+
232
+void check_global_sclab(const SclaBlock *global_sclab,
233
+ IplDeviceComponentEntry *comp_entry,
234
+ IplDeviceComponentList *comp_list)
235
+{
236
+ bool psw_valid = false;
237
+ bool global_psw_valid = false;
238
+ int signed_count = 0;
239
+ int unsigned_count = 0;
240
+ IplDeviceComponentEntry *comp;
241
+
242
+ if (!global_sclab) {
243
+ comp_list->ipl_info_header.iiei |= S390_IIEI_NO_GLOBAL_SCLAB;
244
+ zipl_secure_error("Global SCLAB does not exist");
245
+ return;
246
+ }
247
+
248
+ for_each_rb_entry(comp, comp_list) {
249
+ if (comp->flags & S390_IPL_DEV_COMP_FLAG_SC) {
250
+ psw_valid |= is_psw_valid(comp_entry->addr, comp);
251
+ global_psw_valid |= is_psw_valid(global_sclab->load_psw, comp);
252
+ signed_count += 1;
253
+ } else {
254
+ unsigned_count += 1;
255
+ }
256
+ }
257
+
258
+ /* validate load PSW with PSW specified in the final entry */
259
+ zipl_secure_validate(psw_valid && global_psw_valid, &comp_entry->cei,
260
+ S390_CEI_INVALID_LOAD_PSW, "Invalid PSW");
261
+
262
+ /* compare load PSW with the PSW specified in component */
263
+ zipl_secure_validate(global_sclab->load_psw == comp_entry->addr,
264
+ &comp_entry->cei, S390_CEI_UNMATCHED_SCLAB_LOAD_PSW,
265
+ "Load PSW does not match with PSW in component");
266
+
267
+ /* Unsigned components are not allowed if NUC flag is set in the global SCLAB */
268
+ if ((global_sclab->flags & S390_SCLAB_NUC) && unsigned_count > 0) {
269
+ comp_list->ipl_info_header.iiei |= S390_IIEI_FOUND_UNSIGNED_COMP;
270
+ zipl_secure_error("Unsigned components are not allowed");
271
+ }
272
+
273
+ /*
274
+ * Only one signed component is allowed if SC flag is set in the global SCLAB
275
+ * More than one component in the component table is not allowed
276
+ */
277
+ if ((global_sclab->flags & S390_SCLAB_SC) &&
278
+ (signed_count != 1 || unsigned_count != 0)) {
279
+ comp_list->ipl_info_header.iiei |= S390_IIEI_MORE_SIGNED_COMP;
280
+ zipl_secure_error("Only one signed component is allowed");
281
+ }
282
+}
283
+
284
+static void check_sclab(SclaBlock **global_sclab,
285
+ IplDeviceComponentEntry *comp_entry,
286
+ IplInfoBlockHeader *comp_list_hdr)
287
+{
288
+ SclabOriginLocator *sclab_locator;
289
+ SclaBlock *sclab;
290
+
291
+ /* must be large enough to locate the sclab locator, else implies invalid SCLAB */
292
+ zipl_secure_validate(comp_entry->len >= 8, &comp_entry->cei,
293
+ S390_CEI_INVALID_SCLAB,
294
+ "Signed component too short to contain SCLAB locator");
295
+
296
+ if (comp_entry->cei & S390_CEI_INVALID_SCLAB) {
297
+ return;
298
+ }
299
+
300
+ /* sclab locator is located at the last 8 bytes of the signed comp */
301
+ sclab_locator = (SclabOriginLocator *)(comp_entry->addr +
302
+ comp_entry->len - 8);
303
+
304
+ /* return early if sclab does not exist */
305
+ zipl_secure_validate(magic_match(sclab_locator->magic, ZIPL_MAGIC),
306
+ &comp_entry->cei, S390_CEI_INVALID_SCLAB,
307
+ "Magic does not match. SCLAB does not exist");
308
+
309
+ if (comp_entry->cei & S390_CEI_INVALID_SCLAB) {
310
+ return;
311
+ }
312
+
313
+ zipl_secure_validate(sclab_locator->len >= S390_SCLAB_MIN_LEN, &comp_entry->cei,
314
+ S390_CEI_INVALID_SCLAB_LEN | S390_CEI_INVALID_SCLAB,
315
+ "Invalid SCLAB length");
316
+
317
+ /* return early if sclab is invalid */
318
+ if (comp_entry->cei & S390_CEI_INVALID_SCLAB) {
319
+ return;
320
+ }
321
+
322
+ sclab = (SclaBlock *)(comp_entry->addr + comp_entry->len -
323
+ sclab_locator->len);
324
+
325
+ zipl_secure_validate(sclab->format == 0, &comp_entry->cei,
326
+ S390_CEI_INVALID_SCLAB_FORMAT,
327
+ "Format-0 SCLAB is not being used");
328
+
329
+ if (!(sclab->flags & S390_SCLAB_OPSW)) {
330
+ /* OPSW = 0 - Load PSW field in SCLAB must contain zeros */
331
+ zipl_secure_validate(sclab->load_psw == 0, &comp_entry->cei,
332
+ S390_CEI_SCLAB_LOAD_PSW_NOT_ZERO,
333
+ "Load PSW is not zero when Override PSW bit is zero");
334
+ } else {
335
+ /* OPSW = 1 indicating global SCLAB */
336
+ if (*global_sclab) {
337
+ comp_list_hdr->iiei |= S390_IIEI_MORE_GLOBAL_SCLAB;
338
+ zipl_secure_error("More than one global SCLAB");
339
+ }
340
+ *global_sclab = sclab;
341
+
342
+ /* override load address flag must set to one */
343
+ zipl_secure_validate(sclab->flags & S390_SCLAB_OLA, &comp_entry->cei,
344
+ S390_CEI_SCLAB_OLA_NOT_ONE,
345
+ "OLA flag is not set to one in the global SCLAB");
346
+ }
347
+
348
+ if (!(sclab->flags & S390_SCLAB_OLA)) {
349
+ /* OLA = 0 - Load address field in SCLAB must contain zeros */
350
+ zipl_secure_validate(sclab->load_addr == 0, &comp_entry->cei,
351
+ S390_CEI_SCLAB_LOAD_ADDR_NOT_ZERO,
352
+ "Load Address is not zero when OLA flag is zero");
353
+ } else {
354
+ /* OLA = 1 - Load address field must match storage address of the component */
355
+ zipl_secure_validate(sclab->load_addr == comp_entry->addr, &comp_entry->cei,
356
+ S390_CEI_UNMATCHED_SCLAB_LOAD_ADDR,
357
+ "Load Address does not match with component load address");
358
+ }
359
+
360
+ zipl_secure_validate(~sclab->flags & S390_SCLAB_NUC || sclab->flags & S390_SCLAB_OPSW,
361
+ &comp_entry->cei, S390_CEI_NUC_NOT_IN_GLOBAL_SCLAB,
362
+ "NUC bit is set, but not in the global SCLAB");
363
+
364
+ zipl_secure_validate(~sclab->flags & S390_SCLAB_SC || sclab->flags & S390_SCLAB_OPSW,
365
+ &comp_entry->cei, S390_CEI_SC_NOT_IN_GLOBAL_SCLAB,
366
+ "SC bit is set, but not in the global SCLAB");
367
+}
368
+
369
static int zipl_load_signature(ComponentEntry *entry, uint64_t sig)
370
{
371
if (entry->compdat.sig_info.format != DER_SIGNATURE_FORMAT) {
431
uint8_t *tmp_buf;
432
bool verified;
433
bool signed_found = false;
434
+ bool sclab_found = false;
435
+ SclaBlock *global_sclab = NULL;
436
437
if ((MAX_SIGNED_COMP * CERT_BUF_MAX_LEN) > CERT_BUF_SIZE) {
438
panic("Not enough memory to store certificates");
473
474
/* no signature present (unsigned component) */
475
if (!sig_entry.len) {
476
+ zipl_secure_validate(comp_entry.addr >= S390_UNSIGNED_MIN_ADDR,
477
+ &comp_entry.cei, S390_CEI_INVALID_UNSIGNED_ADDR,
478
+ "Load address for unsigned component is less than 0x2000");
479
+
480
comp_list_add(comp_list, comp_entry);
481
break;
482
}
488
comp_entry.flags = S390_IPL_DEV_COMP_FLAG_SC;
489
signed_found = true;
490
491
+ check_sclab(&global_sclab, &comp_entry, &comp_list->ipl_info_header);
492
+ sclab_found |= !(comp_entry.cei & S390_CEI_INVALID_SCLAB);
493
+
494
cert_entry = (IplSignatureCertificateEntry) { 0 };
495
verified = verify_signature(comp_entry, sig_entry,
496
&cert_entry.len, &cert_table_idx);
536
}
537
}
538
374
- if (!signed_found) {
375
- zipl_secure_error("Secure boot is on, but components are not signed");
376
- }
539
+ zipl_secure_validate(signed_found, &comp_list->ipl_info_header.iiei,
540
+ S390_IIEI_NO_SIGNED_COMP,
541
+ "Secure boot is on, but components are not signed");
542
+
543
+ zipl_secure_validate(sclab_found, &comp_list->ipl_info_header.iiei,
544
+ S390_IIEI_NO_SCLAB, "No recognizable SCLAB");
545
+
546
+ comp_entry = (IplDeviceComponentEntry){ 0 };
547
+ comp_entry.addr = entry->compdat.load_psw;
548
+ check_global_sclab(global_sclab, &comp_entry, comp_list);
549
+ comp_list_add(comp_list, comp_entry);
550
551
*entry_ptr = entry;
552
free((void *)sig_entry.addr);