Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/platforms/pseries/plpks_sed_ops.c
26481 views
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
}
132
133