1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2019 IBM Corporation 4 * Author: Nayna Jain 5 * 6 * - loads keys and hashes stored and controlled by the firmware. 7 */ 8 #include <linux/kernel.h> 9 #include <linux/sched.h> 10 #include <linux/cred.h> 11 #include <linux/err.h> 12 #include <linux/slab.h> 13 #include <linux/of.h> 14 #include <asm/secure_boot.h> 15 #include <asm/secvar.h> 16 #include "keyring_handler.h" 17 18 /* 19 * Get a certificate list blob from the named secure variable. 20 */ 21 static __init void *get_cert_list(u8 *key, unsigned long keylen, uint64_t *size) 22 { 23 int rc; 24 void *db; 25 26 rc = secvar_ops->get(key, keylen, NULL, size); 27 if (rc) { 28 pr_err("Couldn't get size: %d\n", rc); 29 return NULL; 30 } 31 32 db = kmalloc(*size, GFP_KERNEL); 33 if (!db) 34 return NULL; 35 36 rc = secvar_ops->get(key, keylen, db, size); 37 if (rc) { 38 kfree(db); 39 pr_err("Error reading %s var: %d\n", key, rc); 40 return NULL; 41 } 42 43 return db; 44 } 45 46 /* 47 * Load the certs contained in the keys databases into the platform trusted 48 * keyring and the blacklisted X.509 cert SHA256 hashes into the blacklist 49 * keyring. 50 */ 51 static int __init load_powerpc_certs(void) 52 { 53 void *db = NULL, *dbx = NULL; 54 uint64_t dbsize = 0, dbxsize = 0; 55 int rc = 0; 56 struct device_node *node; 57 58 if (!secvar_ops) 59 return -ENODEV; 60 61 /* The following only applies for the edk2-compat backend. */ 62 node = of_find_compatible_node(NULL, NULL, "ibm,edk2-compat-v1"); 63 if (!node) 64 return -ENODEV; 65 66 /* 67 * Get db, and dbx. They might not exist, so it isn't an error if we 68 * can't get them. 69 */ 70 db = get_cert_list("db", 3, &dbsize); 71 if (!db) { 72 pr_err("Couldn't get db list from firmware\n"); 73 } else { 74 rc = parse_efi_signature_list("powerpc:db", db, dbsize, 75 get_handler_for_db); 76 if (rc) 77 pr_err("Couldn't parse db signatures: %d\n", rc); 78 kfree(db); 79 } 80 81 dbx = get_cert_list("dbx", 4, &dbxsize); 82 if (!dbx) { 83 pr_info("Couldn't get dbx list from firmware\n"); 84 } else { 85 rc = parse_efi_signature_list("powerpc:dbx", dbx, dbxsize, 86 get_handler_for_dbx); 87 if (rc) 88 pr_err("Couldn't parse dbx signatures: %d\n", rc); 89 kfree(dbx); 90 } 91 92 of_node_put(node); 93 94 return rc; 95 } 96 late_initcall(load_powerpc_certs); 97