File Index
Files and directories
Sign in
FILE

plpks_sed_ops.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/pseries/plpks_sed_ops.c 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
 19static bool plpks_sed_initialized = false;
 20static bool plpks_sed_available = false;
 21
 22/*
 23 * structure that contains all SED data
 24 */
 25struct 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
 45static 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 */
 70int 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 */
100int 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}
~/ Read-only file preview.