1 // SPDX-License-Identifier: GPL-2.0-only 2 3 // Secure variable implementation using the PowerVM LPAR Platform KeyStore (PLPKS) 4 // 5 // Copyright 2022, 2023 IBM Corporation 6 // Authors: Russell Currey 7 // Andrew Donnellan 8 // Nayna Jain 9 10 #define pr_fmt(fmt) "secvar: "fmt 11 12 #include <linux/printk.h> 13 #include <linux/init.h> 14 #include <linux/types.h> 15 #include <linux/slab.h> 16 #include <linux/string.h> 17 #include <linux/kobject.h> 18 #include <linux/nls.h> 19 #include <asm/machdep.h> 20 #include <asm/secvar.h> 21 #include <asm/plpks.h> 22 23 static u32 get_policy(const char *name) 24 { 25 if ((strcmp(name, "db") == 0) || 26 (strcmp(name, "dbx") == 0) || 27 (strcmp(name, "grubdb") == 0) || 28 (strcmp(name, "grubdbx") == 0) || 29 (strcmp(name, "sbat") == 0)) 30 return (PLPKS_WORLDREADABLE | PLPKS_SIGNEDUPDATE); 31 else 32 return PLPKS_SIGNEDUPDATE; 33 } 34 35 static const char * const plpks_var_names_static[] = { 36 "PK", 37 "moduledb", 38 "trustedcadb", 39 NULL, 40 }; 41 42 static const char * const plpks_var_names_dynamic[] = { 43 "PK", 44 "KEK", 45 "db", 46 "dbx", 47 "grubdb", 48 "grubdbx", 49 "sbat", 50 "moduledb", 51 "trustedcadb", 52 NULL, 53 }; 54 55 static int plpks_get_variable(const char *key, u64 key_len, u8 *data, 56 u64 *data_size) 57 { 58 struct plpks_var var = {0}; 59 int rc = 0; 60 61 // We subtract 1 from key_len because we don't need to include the 62 // null terminator at the end of the string 63 var.name = kcalloc(key_len - 1, sizeof(wchar_t), GFP_KERNEL); 64 if (!var.name) 65 return -ENOMEM; 66 rc = utf8s_to_utf16s(key, key_len - 1, UTF16_LITTLE_ENDIAN, (wchar_t *)var.name, 67 key_len - 1); 68 if (rc < 0) 69 goto err; 70 var.namelen = rc * 2; 71 72 var.os = PLPKS_VAR_LINUX; 73 if (data) { 74 var.data = data; 75 var.datalen = *data_size; 76 } 77 rc = plpks_read_os_var(&var); 78 79 if (rc) 80 goto err; 81 82 *data_size = var.datalen; 83 84 err: 85 kfree(var.name); 86 if (rc && rc != -ENOENT) { 87 pr_err("Failed to read variable '%s': %d\n", key, rc); 88 // Return -EIO since userspace probably doesn't care about the 89 // specific error 90 rc = -EIO; 91 } 92 return rc; 93 } 94 95 static int plpks_set_variable(const char *key, u64 key_len, u8 *data, 96 u64 data_size) 97 { 98 struct plpks_var var = {0}; 99 int rc = 0; 100 u64 flags; 101 102 // Secure variables need to be prefixed with 8 bytes of flags. 103 // We only want to perform the write if we have at least one byte of data. 104 if (data_size <= sizeof(flags)) 105 return -EINVAL; 106 107 // We subtract 1 from key_len because we don't need to include the 108 // null terminator at the end of the string 109 var.name = kcalloc(key_len - 1, sizeof(wchar_t), GFP_KERNEL); 110 if (!var.name) 111 return -ENOMEM; 112 rc = utf8s_to_utf16s(key, key_len - 1, UTF16_LITTLE_ENDIAN, (wchar_t *)var.name, 113 key_len - 1); 114 if (rc < 0) 115 goto err; 116 var.namelen = rc * 2; 117 118 // Flags are contained in the first 8 bytes of the buffer, and are always big-endian 119 flags = be64_to_cpup((__be64 *)data); 120 121 var.datalen = data_size - sizeof(flags); 122 var.data = data + sizeof(flags); 123 var.os = PLPKS_VAR_LINUX; 124 var.policy = get_policy(key); 125 126 // Unlike in the read case, the plpks error code can be useful to 127 // userspace on write, so we return it rather than just -EIO 128 rc = plpks_signed_update_var(&var, flags); 129 130 err: 131 kfree(var.name); 132 return rc; 133 } 134 135 /* 136 * Return the key management mode. 137 * 138 * SB_VERSION is defined as a "1 byte unsigned integer value", taking values 139 * starting from 1. It is owned by the Partition Firmware and its presence 140 * indicates that the key management mode is dynamic. Any failure in 141 * reading SB_VERSION defaults the key management mode to static. The error 142 * codes -ENOENT or -EPERM are expected in static key management mode. An 143 * unexpected error code will have to be investigated. Only signed variables 144 * have null bytes in their names, SB_VERSION does not. 145 * 146 * Return 0 to indicate that the key management mode is static. Otherwise 147 * return the SB_VERSION value to indicate that the key management mode is 148 * dynamic. 149 */ 150 static u8 plpks_get_sb_keymgmt_mode(void) 151 { 152 u8 mode; 153 ssize_t rc; 154 struct plpks_var var = { 155 .component = NULL, 156 .name = "SB_VERSION", 157 .namelen = 10, 158 .datalen = 1, 159 .data = &mode, 160 }; 161 162 rc = plpks_read_fw_var(&var); 163 if (rc) { 164 if (rc != -ENOENT && rc != -EPERM) 165 pr_info("Error %ld reading SB_VERSION from firmware\n", rc); 166 mode = 0; 167 } 168 return mode; 169 } 170 171 /* 172 * PLPKS dynamic secure boot doesn't give us a format string in the same way 173 * OPAL does. Instead, report the format using the SB_VERSION variable in the 174 * keystore. The string, made up by us, takes the form of either 175 * "ibm,plpks-sb-v<n>" or "ibm,plpks-sb-v0", based on the key management mode, 176 * and return the length of the secvar format property. 177 */ 178 static ssize_t plpks_secvar_format(char *buf, size_t bufsize) 179 { 180 u8 mode; 181 182 mode = plpks_get_sb_keymgmt_mode(); 183 return snprintf(buf, bufsize, "ibm,plpks-sb-v%hhu", mode); 184 } 185 186 static int plpks_max_size(u64 *max_size) 187 { 188 // The max object size reported by the hypervisor is accurate for the 189 // object itself, but we use the first 8 bytes of data on write as the 190 // signed update flags, so the max size a user can write is larger. 191 *max_size = (u64)plpks_get_maxobjectsize() + sizeof(u64); 192 193 return 0; 194 } 195 196 static const struct secvar_operations plpks_secvar_ops_static = { 197 .get = plpks_get_variable, 198 .set = plpks_set_variable, 199 .format = plpks_secvar_format, 200 .max_size = plpks_max_size, 201 .var_names = plpks_var_names_static, 202 }; 203 204 static const struct secvar_operations plpks_secvar_ops_dynamic = { 205 .get = plpks_get_variable, 206 .set = plpks_set_variable, 207 .format = plpks_secvar_format, 208 .max_size = plpks_max_size, 209 .var_names = plpks_var_names_dynamic, 210 }; 211 212 static int plpks_secvar_init(void) 213 { 214 u8 mode; 215 216 if (!plpks_is_available()) 217 return -ENODEV; 218 219 mode = plpks_get_sb_keymgmt_mode(); 220 if (mode) 221 return set_secvar_ops(&plpks_secvar_ops_dynamic); 222 return set_secvar_ops(&plpks_secvar_ops_static); 223 } 224 machine_device_initcall(pseries, plpks_secvar_init); 225