1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * POWER LPAR Platform KeyStore(PLPKS) 4 * Copyright (C) 2022 IBM Corporation 5 * Author: Nayna Jain <nayna@linux.ibm.com> 6 * 7 * Provides access to variables stored in Power LPAR Platform KeyStore(PLPKS). 8 */ 9 10 #define pr_fmt(fmt) "plpks: " fmt 11 12 #include <linux/delay.h> 13 #include <linux/errno.h> 14 #include <linux/io.h> 15 #include <linux/printk.h> 16 #include <linux/slab.h> 17 #include <linux/string.h> 18 #include <linux/types.h> 19 #include <asm/hvcall.h> 20 21 #include "plpks.h" 22 23 #define PKS_FW_OWNER 0x1 24 #define PKS_BOOTLOADER_OWNER 0x2 25 #define PKS_OS_OWNER 0x3 26 27 #define LABEL_VERSION 0 28 #define MAX_LABEL_ATTR_SIZE 16 29 #define MAX_NAME_SIZE 239 30 #define MAX_DATA_SIZE 4000 31 32 #define PKS_FLUSH_MAX_TIMEOUT 5000 //msec 33 #define PKS_FLUSH_SLEEP 10 //msec 34 #define PKS_FLUSH_SLEEP_RANGE 400 35 36 static u8 *ospassword; 37 static u16 ospasswordlength; 38 39 // Retrieved with H_PKS_GET_CONFIG 40 static u16 maxpwsize; 41 static u16 maxobjsize; 42 43 struct plpks_auth { 44 u8 version; 45 u8 consumer; 46 __be64 rsvd0; 47 __be32 rsvd1; 48 __be16 passwordlength; 49 u8 password[]; 50 } __packed __aligned(16); 51 52 struct label_attr { 53 u8 prefix[8]; 54 u8 version; 55 u8 os; 56 u8 length; 57 u8 reserved[5]; 58 }; 59 60 struct label { 61 struct label_attr attr; 62 u8 name[MAX_NAME_SIZE]; 63 size_t size; 64 }; 65 66 static int pseries_status_to_err(int rc) 67 { 68 int err; 69 70 switch (rc) { 71 case H_SUCCESS: 72 err = 0; 73 break; 74 case H_FUNCTION: 75 err = -ENXIO; 76 break; 77 case H_P1: 78 case H_P2: 79 case H_P3: 80 case H_P4: 81 case H_P5: 82 case H_P6: 83 err = -EINVAL; 84 break; 85 case H_NOT_FOUND: 86 err = -ENOENT; 87 break; 88 case H_BUSY: 89 err = -EBUSY; 90 break; 91 case H_AUTHORITY: 92 err = -EPERM; 93 break; 94 case H_NO_MEM: 95 err = -ENOMEM; 96 break; 97 case H_RESOURCE: 98 err = -EEXIST; 99 break; 100 case H_TOO_BIG: 101 err = -EFBIG; 102 break; 103 case H_STATE: 104 err = -EIO; 105 break; 106 case H_R_STATE: 107 err = -EIO; 108 break; 109 case H_IN_USE: 110 err = -EEXIST; 111 break; 112 case H_ABORTED: 113 err = -EINTR; 114 break; 115 default: 116 err = -EINVAL; 117 } 118 119 return err; 120 } 121 122 static int plpks_gen_password(void) 123 { 124 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; 125 u8 *password, consumer = PKS_OS_OWNER; 126 int rc; 127 128 password = kzalloc(maxpwsize, GFP_KERNEL); 129 if (!password) 130 return -ENOMEM; 131 132 rc = plpar_hcall(H_PKS_GEN_PASSWORD, retbuf, consumer, 0, 133 virt_to_phys(password), maxpwsize); 134 135 if (!rc) { 136 ospasswordlength = maxpwsize; 137 ospassword = kzalloc(maxpwsize, GFP_KERNEL); 138 if (!ospassword) { 139 kfree(password); 140 return -ENOMEM; 141 } 142 memcpy(ospassword, password, ospasswordlength); 143 } else { 144 if (rc == H_IN_USE) { 145 pr_warn("Password is already set for POWER LPAR Platform KeyStore\n"); 146 rc = 0; 147 } else { 148 goto out; 149 } 150 } 151 out: 152 kfree(password); 153 154 return pseries_status_to_err(rc); 155 } 156 157 static struct plpks_auth *construct_auth(u8 consumer) 158 { 159 struct plpks_auth *auth; 160 161 if (consumer > PKS_OS_OWNER) 162 return ERR_PTR(-EINVAL); 163 164 auth = kmalloc(struct_size(auth, password, maxpwsize), GFP_KERNEL); 165 if (!auth) 166 return ERR_PTR(-ENOMEM); 167 168 auth->version = 1; 169 auth->consumer = consumer; 170 auth->rsvd0 = 0; 171 auth->rsvd1 = 0; 172 173 if (consumer == PKS_FW_OWNER || consumer == PKS_BOOTLOADER_OWNER) { 174 auth->passwordlength = 0; 175 return auth; 176 } 177 178 memcpy(auth->password, ospassword, ospasswordlength); 179 180 auth->passwordlength = cpu_to_be16(ospasswordlength); 181 182 return auth; 183 } 184 185 /** 186 * Label is combination of label attributes + name. 187 * Label attributes are used internally by kernel and not exposed to the user. 188 */ 189 static struct label *construct_label(char *component, u8 varos, u8 *name, 190 u16 namelen) 191 { 192 struct label *label; 193 size_t slen; 194 195 if (!name || namelen > MAX_NAME_SIZE) 196 return ERR_PTR(-EINVAL); 197 198 slen = strlen(component); 199 if (component && slen > sizeof(label->attr.prefix)) 200 return ERR_PTR(-EINVAL); 201 202 label = kzalloc(sizeof(*label), GFP_KERNEL); 203 if (!label) 204 return ERR_PTR(-ENOMEM); 205 206 if (component) 207 memcpy(&label->attr.prefix, component, slen); 208 209 label->attr.version = LABEL_VERSION; 210 label->attr.os = varos; 211 label->attr.length = MAX_LABEL_ATTR_SIZE; 212 memcpy(&label->name, name, namelen); 213 214 label->size = sizeof(struct label_attr) + namelen; 215 216 return label; 217 } 218 219 static int _plpks_get_config(void) 220 { 221 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; 222 struct { 223 u8 version; 224 u8 flags; 225 __be32 rsvd0; 226 __be16 maxpwsize; 227 __be16 maxobjlabelsize; 228 __be16 maxobjsize; 229 __be32 totalsize; 230 __be32 usedspace; 231 __be32 supportedpolicies; 232 __be64 rsvd1; 233 } __packed config; 234 size_t size; 235 int rc; 236 237 size = sizeof(config); 238 239 rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(&config), size); 240 241 if (rc != H_SUCCESS) 242 return pseries_status_to_err(rc); 243 244 maxpwsize = be16_to_cpu(config.maxpwsize); 245 maxobjsize = be16_to_cpu(config.maxobjsize); 246 247 return 0; 248 } 249 250 static int plpks_confirm_object_flushed(struct label *label, 251 struct plpks_auth *auth) 252 { 253 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; 254 u64 timeout = 0; 255 u8 status; 256 int rc; 257 258 do { 259 rc = plpar_hcall(H_PKS_CONFIRM_OBJECT_FLUSHED, retbuf, 260 virt_to_phys(auth), virt_to_phys(label), 261 label->size); 262 263 status = retbuf[0]; 264 if (rc) { 265 if (rc == H_NOT_FOUND && status == 1) 266 rc = 0; 267 break; 268 } 269 270 if (!rc && status == 1) 271 break; 272 273 usleep_range(PKS_FLUSH_SLEEP, 274 PKS_FLUSH_SLEEP + PKS_FLUSH_SLEEP_RANGE); 275 timeout = timeout + PKS_FLUSH_SLEEP; 276 } while (timeout < PKS_FLUSH_MAX_TIMEOUT); 277 278 rc = pseries_status_to_err(rc); 279 280 return rc; 281 } 282 283 int plpks_write_var(struct plpks_var var) 284 { 285 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; 286 struct plpks_auth *auth; 287 struct label *label; 288 int rc; 289 290 if (!var.component || !var.data || var.datalen <= 0 || 291 var.namelen > MAX_NAME_SIZE || var.datalen > MAX_DATA_SIZE) 292 return -EINVAL; 293 294 if (var.policy & SIGNEDUPDATE) 295 return -EINVAL; 296 297 auth = construct_auth(PKS_OS_OWNER); 298 if (IS_ERR(auth)) 299 return PTR_ERR(auth); 300 301 label = construct_label(var.component, var.os, var.name, var.namelen); 302 if (IS_ERR(label)) { 303 rc = PTR_ERR(label); 304 goto out; 305 } 306 307 rc = plpar_hcall(H_PKS_WRITE_OBJECT, retbuf, virt_to_phys(auth), 308 virt_to_phys(label), label->size, var.policy, 309 virt_to_phys(var.data), var.datalen); 310 311 if (!rc) 312 rc = plpks_confirm_object_flushed(label, auth); 313 314 if (rc) 315 pr_err("Failed to write variable %s for component %s with error %d\n", 316 var.name, var.component, rc); 317 318 rc = pseries_status_to_err(rc); 319 kfree(label); 320 out: 321 kfree(auth); 322 323 return rc; 324 } 325 326 int plpks_remove_var(char *component, u8 varos, struct plpks_var_name vname) 327 { 328 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; 329 struct plpks_auth *auth; 330 struct label *label; 331 int rc; 332 333 if (!component || vname.namelen > MAX_NAME_SIZE) 334 return -EINVAL; 335 336 auth = construct_auth(PKS_OS_OWNER); 337 if (IS_ERR(auth)) 338 return PTR_ERR(auth); 339 340 label = construct_label(component, varos, vname.name, vname.namelen); 341 if (IS_ERR(label)) { 342 rc = PTR_ERR(label); 343 goto out; 344 } 345 346 rc = plpar_hcall(H_PKS_REMOVE_OBJECT, retbuf, virt_to_phys(auth), 347 virt_to_phys(label), label->size); 348 349 if (!rc) 350 rc = plpks_confirm_object_flushed(label, auth); 351 352 if (rc) 353 pr_err("Failed to remove variable %s for component %s with error %d\n", 354 vname.name, component, rc); 355 356 rc = pseries_status_to_err(rc); 357 kfree(label); 358 out: 359 kfree(auth); 360 361 return rc; 362 } 363 364 static int plpks_read_var(u8 consumer, struct plpks_var *var) 365 { 366 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; 367 struct plpks_auth *auth; 368 struct label *label; 369 u8 *output; 370 int rc; 371 372 if (var->namelen > MAX_NAME_SIZE) 373 return -EINVAL; 374 375 auth = construct_auth(PKS_OS_OWNER); 376 if (IS_ERR(auth)) 377 return PTR_ERR(auth); 378 379 label = construct_label(var->component, var->os, var->name, 380 var->namelen); 381 if (IS_ERR(label)) { 382 rc = PTR_ERR(label); 383 goto out_free_auth; 384 } 385 386 output = kzalloc(maxobjsize, GFP_KERNEL); 387 if (!output) { 388 rc = -ENOMEM; 389 goto out_free_label; 390 } 391 392 rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth), 393 virt_to_phys(label), label->size, virt_to_phys(output), 394 maxobjsize); 395 396 if (rc != H_SUCCESS) { 397 pr_err("Failed to read variable %s for component %s with error %d\n", 398 var->name, var->component, rc); 399 rc = pseries_status_to_err(rc); 400 goto out_free_output; 401 } 402 403 if (var->datalen == 0 || var->datalen > retbuf[0]) 404 var->datalen = retbuf[0]; 405 406 var->data = kzalloc(var->datalen, GFP_KERNEL); 407 if (!var->data) { 408 rc = -ENOMEM; 409 goto out_free_output; 410 } 411 var->policy = retbuf[1]; 412 413 memcpy(var->data, output, var->datalen); 414 rc = 0; 415 416 out_free_output: 417 kfree(output); 418 out_free_label: 419 kfree(label); 420 out_free_auth: 421 kfree(auth); 422 423 return rc; 424 } 425 426 int plpks_read_os_var(struct plpks_var *var) 427 { 428 return plpks_read_var(PKS_OS_OWNER, var); 429 } 430 431 int plpks_read_fw_var(struct plpks_var *var) 432 { 433 return plpks_read_var(PKS_FW_OWNER, var); 434 } 435 436 int plpks_read_bootloader_var(struct plpks_var *var) 437 { 438 return plpks_read_var(PKS_BOOTLOADER_OWNER, var); 439 } 440 441 static __init int pseries_plpks_init(void) 442 { 443 int rc; 444 445 rc = _plpks_get_config(); 446 447 if (rc) { 448 pr_err("POWER LPAR Platform KeyStore is not supported or enabled\n"); 449 return rc; 450 } 451 452 rc = plpks_gen_password(); 453 if (rc) 454 pr_err("Failed setting POWER LPAR Platform KeyStore Password\n"); 455 else 456 pr_info("POWER LPAR Platform KeyStore initialized successfully\n"); 457 458 return rc; 459 } 460 arch_initcall(pseries_plpks_init); 461