Path: blob/master/arch/powerpc/platforms/pseries/plpks_sed_ops.c
26481 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* POWER Platform specific code for non-volatile SED key access3* Copyright (C) 2022 IBM Corporation4*5* Define operations for SED Opal to read/write keys6* from POWER LPAR Platform KeyStore(PLPKS).7*8* Self Encrypting Drives(SED) key storage using PLPKS9*/1011#include <linux/kernel.h>12#include <linux/slab.h>13#include <linux/string.h>14#include <linux/ioctl.h>15#include <linux/sed-opal-key.h>16#include <asm/plpks.h>1718static bool plpks_sed_initialized = false;19static bool plpks_sed_available = false;2021/*22* structure that contains all SED data23*/24struct plpks_sed_object_data {25u_char version;26u_char pad1[7];27u_long authority;28u_long range;29u_int key_len;30u_char key[32];31};3233#define PLPKS_SED_OBJECT_DATA_V0 034#define PLPKS_SED_MANGLED_LABEL "/default/pri"35#define PLPKS_SED_COMPONENT "sed-opal"36#define PLPKS_SED_KEY "opal-boot-pin"3738/*39* authority is admin1 and range is global40*/41#define PLPKS_SED_AUTHORITY 0x000000090001000142#define PLPKS_SED_RANGE 0x00000802000000014344static void plpks_init_var(struct plpks_var *var, char *keyname)45{46if (!plpks_sed_initialized) {47plpks_sed_initialized = true;48plpks_sed_available = plpks_is_available();49if (!plpks_sed_available)50pr_err("SED: plpks not available\n");51}5253var->name = keyname;54var->namelen = strlen(keyname);55if (strcmp(PLPKS_SED_KEY, keyname) == 0) {56var->name = PLPKS_SED_MANGLED_LABEL;57var->namelen = strlen(keyname);58}59var->policy = PLPKS_WORLDREADABLE;60var->os = PLPKS_VAR_COMMON;61var->data = NULL;62var->datalen = 0;63var->component = PLPKS_SED_COMPONENT;64}6566/*67* Read the SED Opal key from PLPKS given the label68*/69int sed_read_key(char *keyname, char *key, u_int *keylen)70{71struct plpks_var var;72struct plpks_sed_object_data data;73int ret;74u_int len;7576plpks_init_var(&var, keyname);7778if (!plpks_sed_available)79return -EOPNOTSUPP;8081var.data = (u8 *)&data;82var.datalen = sizeof(data);8384ret = plpks_read_os_var(&var);85if (ret != 0)86return ret;8788len = min_t(u16, be32_to_cpu(data.key_len), var.datalen);89memcpy(key, data.key, len);90key[len] = '\0';91*keylen = len;9293return 0;94}9596/*97* Write the SED Opal key to PLPKS given the label98*/99int sed_write_key(char *keyname, char *key, u_int keylen)100{101struct plpks_var var;102struct plpks_sed_object_data data;103struct plpks_var_name vname;104105plpks_init_var(&var, keyname);106107if (!plpks_sed_available)108return -EOPNOTSUPP;109110var.datalen = sizeof(struct plpks_sed_object_data);111var.data = (u8 *)&data;112113/* initialize SED object */114data.version = PLPKS_SED_OBJECT_DATA_V0;115data.authority = cpu_to_be64(PLPKS_SED_AUTHORITY);116data.range = cpu_to_be64(PLPKS_SED_RANGE);117memset(&data.pad1, '\0', sizeof(data.pad1));118data.key_len = cpu_to_be32(keylen);119memcpy(data.key, (char *)key, keylen);120121/*122* Key update requires remove first. The return value123* is ignored since it's okay if the key doesn't exist.124*/125vname.namelen = var.namelen;126vname.name = var.name;127plpks_remove_var(var.component, var.os, vname);128129return plpks_write_var(var);130}131132133