Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries: PLPKS SED Opal keystore support

Define operations for SED Opal to read/write keys
from POWER LPAR Platform KeyStore(PLPKS). This allows
non-volatile storage of SED Opal keys.

Signed-off-by: Greg Joyce <gjoyce@linux.vnet.ibm.com>
Reviewed-by: Jonathan Derrick <jonathan.derrick@linux.dev>
Link: https://lore.kernel.org/r/20231004201957.1451669-4-gjoyce@linux.vnet.ibm.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Greg Joyce and committed by
Jens Axboe
ec8cf230 5dd33972

+139
+6
arch/powerpc/platforms/pseries/Kconfig
··· 164 164 # This option is selected by in-kernel consumers that require 165 165 # access to the PKS. 166 166 167 + config PSERIES_PLPKS_SED 168 + depends on PPC_PSERIES 169 + bool 170 + # This option is selected by in-kernel consumers that require 171 + # access to the SED PKS keystore. 172 + 167 173 config PAPR_SCM 168 174 depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM 169 175 tristate "Support for the PAPR Storage Class Memory interface"
+1
arch/powerpc/platforms/pseries/Makefile
··· 29 29 obj-$(CONFIG_FA_DUMP) += rtas-fadump.o 30 30 obj-$(CONFIG_PSERIES_PLPKS) += plpks.o 31 31 obj-$(CONFIG_PPC_SECURE_BOOT) += plpks-secvar.o 32 + obj-$(CONFIG_PSERIES_PLPKS_SED) += plpks_sed_ops.o 32 33 obj-$(CONFIG_SUSPEND) += suspend.o 33 34 obj-$(CONFIG_PPC_VAS) += vas.o vas-sysfs.o 34 35
+131
arch/powerpc/platforms/pseries/plpks_sed_ops.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * POWER Platform specific code for non-volatile SED key access 4 + * Copyright (C) 2022 IBM Corporation 5 + * 6 + * Define operations for SED Opal to read/write keys 7 + * from POWER LPAR Platform KeyStore(PLPKS). 8 + * 9 + * Self Encrypting Drives(SED) key storage using PLPKS 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/slab.h> 14 + #include <linux/string.h> 15 + #include <linux/ioctl.h> 16 + #include <linux/sed-opal-key.h> 17 + #include <asm/plpks.h> 18 + 19 + static bool plpks_sed_initialized = false; 20 + static bool plpks_sed_available = false; 21 + 22 + /* 23 + * structure that contains all SED data 24 + */ 25 + struct plpks_sed_object_data { 26 + u_char version; 27 + u_char pad1[7]; 28 + u_long authority; 29 + u_long range; 30 + u_int key_len; 31 + u_char key[32]; 32 + }; 33 + 34 + #define PLPKS_SED_OBJECT_DATA_V0 0 35 + #define PLPKS_SED_MANGLED_LABEL "/default/pri" 36 + #define PLPKS_SED_COMPONENT "sed-opal" 37 + #define PLPKS_SED_KEY "opal-boot-pin" 38 + 39 + /* 40 + * authority is admin1 and range is global 41 + */ 42 + #define PLPKS_SED_AUTHORITY 0x0000000900010001 43 + #define PLPKS_SED_RANGE 0x0000080200000001 44 + 45 + static void plpks_init_var(struct plpks_var *var, char *keyname) 46 + { 47 + if (!plpks_sed_initialized) { 48 + plpks_sed_initialized = true; 49 + plpks_sed_available = plpks_is_available(); 50 + if (!plpks_sed_available) 51 + pr_err("SED: plpks not available\n"); 52 + } 53 + 54 + var->name = keyname; 55 + var->namelen = strlen(keyname); 56 + if (strcmp(PLPKS_SED_KEY, keyname) == 0) { 57 + var->name = PLPKS_SED_MANGLED_LABEL; 58 + var->namelen = strlen(keyname); 59 + } 60 + var->policy = PLPKS_WORLDREADABLE; 61 + var->os = PLPKS_VAR_COMMON; 62 + var->data = NULL; 63 + var->datalen = 0; 64 + var->component = PLPKS_SED_COMPONENT; 65 + } 66 + 67 + /* 68 + * Read the SED Opal key from PLPKS given the label 69 + */ 70 + int sed_read_key(char *keyname, char *key, u_int *keylen) 71 + { 72 + struct plpks_var var; 73 + struct plpks_sed_object_data data; 74 + int ret; 75 + u_int len; 76 + 77 + plpks_init_var(&var, keyname); 78 + 79 + if (!plpks_sed_available) 80 + return -EOPNOTSUPP; 81 + 82 + var.data = (u8 *)&data; 83 + var.datalen = sizeof(data); 84 + 85 + ret = plpks_read_os_var(&var); 86 + if (ret != 0) 87 + return ret; 88 + 89 + len = min_t(u16, be32_to_cpu(data.key_len), var.datalen); 90 + memcpy(key, data.key, len); 91 + key[len] = '\0'; 92 + *keylen = len; 93 + 94 + return 0; 95 + } 96 + 97 + /* 98 + * Write the SED Opal key to PLPKS given the label 99 + */ 100 + int sed_write_key(char *keyname, char *key, u_int keylen) 101 + { 102 + struct plpks_var var; 103 + struct plpks_sed_object_data data; 104 + struct plpks_var_name vname; 105 + 106 + plpks_init_var(&var, keyname); 107 + 108 + if (!plpks_sed_available) 109 + return -EOPNOTSUPP; 110 + 111 + var.datalen = sizeof(struct plpks_sed_object_data); 112 + var.data = (u8 *)&data; 113 + 114 + /* initialize SED object */ 115 + data.version = PLPKS_SED_OBJECT_DATA_V0; 116 + data.authority = cpu_to_be64(PLPKS_SED_AUTHORITY); 117 + data.range = cpu_to_be64(PLPKS_SED_RANGE); 118 + memset(&data.pad1, '\0', sizeof(data.pad1)); 119 + data.key_len = cpu_to_be32(keylen); 120 + memcpy(data.key, (char *)key, keylen); 121 + 122 + /* 123 + * Key update requires remove first. The return value 124 + * is ignored since it's okay if the key doesn't exist. 125 + */ 126 + vname.namelen = var.namelen; 127 + vname.name = var.name; 128 + plpks_remove_var(var.component, var.os, vname); 129 + 130 + return plpks_write_var(var); 131 + }
+1
block/Kconfig
··· 186 186 bool "Logic for interfacing with Opal enabled SEDs" 187 187 depends on KEYS 188 188 select PSERIES_PLPKS if PPC_PSERIES 189 + select PSERIES_PLPKS_SED if PPC_PSERIES 189 190 help 190 191 Builds Logic for interfacing with Opal enabled controllers. 191 192 Enabling this option enables users to setup/unlock/lock