1 // SPDX-License-Identifier: GPL-2.0-only
2
3 // Secure variable implementation using the PowerVM LPAR Platform KeyStore (PLPKS)
4 //
5 // Copyright 2022, 2023 IBM Corporation
6 // Authors: Russell Currey
7 // Andrew Donnellan
8 // Nayna Jain
9
10 #define pr_fmt(fmt) "secvar: "fmt
11
12 #include <linux/printk.h>
13 #include <linux/init.h>
14 #include <linux/types.h>
15 #include <linux/slab.h>
16 #include <linux/string.h>
17 #include <linux/kobject.h>
18 #include <linux/nls.h>
19 #include <asm/machdep.h>
20 #include <asm/secvar.h>
21 #include <asm/plpks.h>
22
23 // Config attributes for sysfs
24 #define PLPKS_CONFIG_ATTR(name, fmt, func) \
25 static ssize_t name##_show(struct kobject *kobj, \
26 struct kobj_attribute *attr, \
27 char *buf) \
28 { \
29 return sysfs_emit(buf, fmt, func()); \
30 } \
31 static struct kobj_attribute attr_##name = __ATTR_RO(name)
32
33 PLPKS_CONFIG_ATTR(version, "%u\n", plpks_get_version);
34 PLPKS_CONFIG_ATTR(max_object_size, "%u\n", plpks_get_maxobjectsize);
35 PLPKS_CONFIG_ATTR(total_size, "%u\n", plpks_get_totalsize);
36 PLPKS_CONFIG_ATTR(used_space, "%u\n", plpks_get_usedspace);
37 PLPKS_CONFIG_ATTR(supported_policies, "%08x\n", plpks_get_supportedpolicies);
38 PLPKS_CONFIG_ATTR(signed_update_algorithms, "%016llx\n", plpks_get_signedupdatealgorithms);
39
40 static const struct attribute *config_attrs[] = {
41 &attr_version.attr,
42 &attr_max_object_size.attr,
43 &attr_total_size.attr,
44 &attr_used_space.attr,
45 &attr_supported_policies.attr,
46 &attr_signed_update_algorithms.attr,
47 NULL,
48 };
49
get_policy(const char * name)50 static u32 get_policy(const char *name)
51 {
52 if ((strcmp(name, "db") == 0) ||
53 (strcmp(name, "dbx") == 0) ||
54 (strcmp(name, "grubdb") == 0) ||
55 (strcmp(name, "grubdbx") == 0) ||
56 (strcmp(name, "sbat") == 0))
57 return (PLPKS_WORLDREADABLE | PLPKS_SIGNEDUPDATE);
58 else
59 return PLPKS_SIGNEDUPDATE;
60 }
61
62 static const char * const plpks_var_names_static[] = {
63 "PK",
64 "moduledb",
65 "trustedcadb",
66 NULL,
67 };
68
69 static const char * const plpks_var_names_dynamic[] = {
70 "PK",
71 "KEK",
72 "db",
73 "dbx",
74 "grubdb",
75 "grubdbx",
76 "sbat",
77 "moduledb",
78 "trustedcadb",
79 NULL,
80 };
81
plpks_get_variable(const char * key,u64 key_len,u8 * data,u64 * data_size)82 static int plpks_get_variable(const char *key, u64 key_len, u8 *data,
83 u64 *data_size)
84 {
85 struct plpks_var var = {0};
86 int rc = 0;
87
88 // We subtract 1 from key_len because we don't need to include the
89 // null terminator at the end of the string
90 var.name = kcalloc(key_len - 1, sizeof(wchar_t), GFP_KERNEL);
91 if (!var.name)
92 return -ENOMEM;
93 rc = utf8s_to_utf16s(key, key_len - 1, UTF16_LITTLE_ENDIAN, (wchar_t *)var.name,
94 key_len - 1);
95 if (rc < 0)
96 goto err;
97 var.namelen = rc * 2;
98
99 var.os = PLPKS_VAR_LINUX;
100 if (data) {
101 var.data = data;
102 var.datalen = *data_size;
103 }
104 rc = plpks_read_os_var(&var);
105
106 if (rc)
107 goto err;
108
109 *data_size = var.datalen;
110
111 err:
112 kfree(var.name);
113 if (rc && rc != -ENOENT) {
114 pr_err("Failed to read variable '%s': %d\n", key, rc);
115 // Return -EIO since userspace probably doesn't care about the
116 // specific error
117 rc = -EIO;
118 }
119 return rc;
120 }
121
plpks_set_variable(const char * key,u64 key_len,u8 * data,u64 data_size)122 static int plpks_set_variable(const char *key, u64 key_len, u8 *data,
123 u64 data_size)
124 {
125 struct plpks_var var = {0};
126 int rc = 0;
127 u64 flags;
128
129 // Secure variables need to be prefixed with 8 bytes of flags.
130 // We only want to perform the write if we have at least one byte of data.
131 if (data_size <= sizeof(flags))
132 return -EINVAL;
133
134 // We subtract 1 from key_len because we don't need to include the
135 // null terminator at the end of the string
136 var.name = kcalloc(key_len - 1, sizeof(wchar_t), GFP_KERNEL);
137 if (!var.name)
138 return -ENOMEM;
139 rc = utf8s_to_utf16s(key, key_len - 1, UTF16_LITTLE_ENDIAN, (wchar_t *)var.name,
140 key_len - 1);
141 if (rc < 0)
142 goto err;
143 var.namelen = rc * 2;
144
145 // Flags are contained in the first 8 bytes of the buffer, and are always big-endian
146 flags = be64_to_cpup((__be64 *)data);
147
148 var.datalen = data_size - sizeof(flags);
149 var.data = data + sizeof(flags);
150 var.os = PLPKS_VAR_LINUX;
151 var.policy = get_policy(key);
152
153 // Unlike in the read case, the plpks error code can be useful to
154 // userspace on write, so we return it rather than just -EIO
155 rc = plpks_signed_update_var(&var, flags);
156
157 err:
158 kfree(var.name);
159 return rc;
160 }
161
162 /*
163 * Return the key management mode.
164 *
165 * SB_VERSION is defined as a "1 byte unsigned integer value", taking values
166 * starting from 1. It is owned by the Partition Firmware and its presence
167 * indicates that the key management mode is dynamic. Any failure in
168 * reading SB_VERSION defaults the key management mode to static. The error
169 * codes -ENOENT or -EPERM are expected in static key management mode. An
170 * unexpected error code will have to be investigated. Only signed variables
171 * have null bytes in their names, SB_VERSION does not.
172 *
173 * Return 0 to indicate that the key management mode is static. Otherwise
174 * return the SB_VERSION value to indicate that the key management mode is
175 * dynamic.
176 */
plpks_get_sb_keymgmt_mode(void)177 static u8 plpks_get_sb_keymgmt_mode(void)
178 {
179 u8 mode;
180 ssize_t rc;
181 struct plpks_var var = {
182 .component = NULL,
183 .name = "SB_VERSION",
184 .namelen = 10,
185 .datalen = 1,
186 .data = &mode,
187 };
188
189 rc = plpks_read_fw_var(&var);
190 if (rc) {
191 if (rc != -ENOENT && rc != -EPERM)
192 pr_info("Error %ld reading SB_VERSION from firmware\n", rc);
193 mode = 0;
194 }
195 return mode;
196 }
197
198 /*
199 * PLPKS dynamic secure boot doesn't give us a format string in the same way
200 * OPAL does. Instead, report the format using the SB_VERSION variable in the
201 * keystore. The string, made up by us, takes the form of either
202 * "ibm,plpks-sb-v<n>" or "ibm,plpks-sb-v0", based on the key management mode,
203 * and return the length of the secvar format property.
204 */
plpks_secvar_format(char * buf,size_t bufsize)205 static ssize_t plpks_secvar_format(char *buf, size_t bufsize)
206 {
207 u8 mode;
208
209 mode = plpks_get_sb_keymgmt_mode();
210 return snprintf(buf, bufsize, "ibm,plpks-sb-v%hhu", mode);
211 }
212
plpks_max_size(u64 * max_size)213 static int plpks_max_size(u64 *max_size)
214 {
215 // The max object size reported by the hypervisor is accurate for the
216 // object itself, but we use the first 8 bytes of data on write as the
217 // signed update flags, so the max size a user can write is larger.
218 *max_size = (u64)plpks_get_maxobjectsize() + sizeof(u64);
219
220 return 0;
221 }
222
223 static const struct secvar_operations plpks_secvar_ops_static = {
224 .get = plpks_get_variable,
225 .set = plpks_set_variable,
226 .format = plpks_secvar_format,
227 .max_size = plpks_max_size,
228 .config_attrs = config_attrs,
229 .var_names = plpks_var_names_static,
230 };
231
232 static const struct secvar_operations plpks_secvar_ops_dynamic = {
233 .get = plpks_get_variable,
234 .set = plpks_set_variable,
235 .format = plpks_secvar_format,
236 .max_size = plpks_max_size,
237 .config_attrs = config_attrs,
238 .var_names = plpks_var_names_dynamic,
239 };
240
plpks_secvar_init(void)241 static int plpks_secvar_init(void)
242 {
243 u8 mode;
244
245 if (!plpks_is_available())
246 return -ENODEV;
247
248 mode = plpks_get_sb_keymgmt_mode();
249 if (mode)
250 return set_secvar_ops(&plpks_secvar_ops_dynamic);
251 return set_secvar_ops(&plpks_secvar_ops_static);
252 }
253 machine_device_initcall(pseries, plpks_secvar_init);
254