powerpc/pseries: Implement signed update for PLPKS objects
[linux-block.git] / arch / powerpc / platforms / pseries / plpks.c
CommitLineData
2454a7af
NJ
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * POWER LPAR Platform KeyStore(PLPKS)
4 * Copyright (C) 2022 IBM Corporation
5 * Author: Nayna Jain <nayna@linux.ibm.com>
6 *
7 * Provides access to variables stored in Power LPAR Platform KeyStore(PLPKS).
8 */
9
10#define pr_fmt(fmt) "plpks: " fmt
11
12#include <linux/delay.h>
13#include <linux/errno.h>
14#include <linux/io.h>
15#include <linux/printk.h>
16#include <linux/slab.h>
17#include <linux/string.h>
18#include <linux/types.h>
19#include <asm/hvcall.h>
a66de528 20#include <asm/machdep.h>
90b74e30 21#include <asm/plpks.h>
2454a7af 22
2454a7af
NJ
23static u8 *ospassword;
24static u16 ospasswordlength;
25
26// Retrieved with H_PKS_GET_CONFIG
119da30d
NJ
27static u8 version;
28static u16 objoverhead;
2454a7af
NJ
29static u16 maxpwsize;
30static u16 maxobjsize;
119da30d
NJ
31static s16 maxobjlabelsize;
32static u32 totalsize;
33static u32 usedspace;
34static u32 supportedpolicies;
35static u32 maxlargeobjectsize;
36static u64 signedupdatealgorithms;
2454a7af
NJ
37
38struct plpks_auth {
39 u8 version;
40 u8 consumer;
41 __be64 rsvd0;
42 __be32 rsvd1;
43 __be16 passwordlength;
44 u8 password[];
45} __packed __aligned(16);
46
47struct label_attr {
48 u8 prefix[8];
49 u8 version;
50 u8 os;
51 u8 length;
52 u8 reserved[5];
53};
54
55struct label {
56 struct label_attr attr;
3def7a3e 57 u8 name[PLPKS_MAX_NAME_SIZE];
2454a7af
NJ
58 size_t size;
59};
60
61static int pseries_status_to_err(int rc)
62{
63 int err;
64
65 switch (rc) {
66 case H_SUCCESS:
67 err = 0;
68 break;
69 case H_FUNCTION:
70 err = -ENXIO;
71 break;
af223e17 72 case H_PARAMETER:
2454a7af
NJ
73 case H_P2:
74 case H_P3:
75 case H_P4:
76 case H_P5:
77 case H_P6:
78 err = -EINVAL;
79 break;
80 case H_NOT_FOUND:
81 err = -ENOENT;
82 break;
83 case H_BUSY:
899d9b8f
NJ
84 case H_LONG_BUSY_ORDER_1_MSEC:
85 case H_LONG_BUSY_ORDER_10_MSEC:
86 case H_LONG_BUSY_ORDER_100_MSEC:
87 case H_LONG_BUSY_ORDER_1_SEC:
88 case H_LONG_BUSY_ORDER_10_SEC:
89 case H_LONG_BUSY_ORDER_100_SEC:
2454a7af
NJ
90 err = -EBUSY;
91 break;
92 case H_AUTHORITY:
93 err = -EPERM;
94 break;
95 case H_NO_MEM:
96 err = -ENOMEM;
97 break;
98 case H_RESOURCE:
99 err = -EEXIST;
100 break;
101 case H_TOO_BIG:
102 err = -EFBIG;
103 break;
104 case H_STATE:
105 err = -EIO;
106 break;
107 case H_R_STATE:
108 err = -EIO;
109 break;
110 case H_IN_USE:
111 err = -EEXIST;
112 break;
113 case H_ABORTED:
bb8e4c7c 114 err = -EIO;
2454a7af
NJ
115 break;
116 default:
117 err = -EINVAL;
118 }
119
120 return err;
121}
122
123static int plpks_gen_password(void)
124{
125 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
3def7a3e 126 u8 *password, consumer = PLPKS_OS_OWNER;
2454a7af
NJ
127 int rc;
128
fcf63d6b
AD
129 // The password must not cross a page boundary, so we align to the next power of 2
130 password = kzalloc(roundup_pow_of_two(maxpwsize), GFP_KERNEL);
2454a7af
NJ
131 if (!password)
132 return -ENOMEM;
133
134 rc = plpar_hcall(H_PKS_GEN_PASSWORD, retbuf, consumer, 0,
135 virt_to_phys(password), maxpwsize);
136
137 if (!rc) {
138 ospasswordlength = maxpwsize;
139 ospassword = kzalloc(maxpwsize, GFP_KERNEL);
140 if (!ospassword) {
141 kfree(password);
142 return -ENOMEM;
143 }
144 memcpy(ospassword, password, ospasswordlength);
145 } else {
146 if (rc == H_IN_USE) {
147 pr_warn("Password is already set for POWER LPAR Platform KeyStore\n");
148 rc = 0;
149 } else {
150 goto out;
151 }
152 }
153out:
154 kfree(password);
155
156 return pseries_status_to_err(rc);
157}
158
159static struct plpks_auth *construct_auth(u8 consumer)
160{
161 struct plpks_auth *auth;
162
3def7a3e 163 if (consumer > PLPKS_OS_OWNER)
2454a7af
NJ
164 return ERR_PTR(-EINVAL);
165
fcf63d6b
AD
166 // The auth structure must not cross a page boundary and must be
167 // 16 byte aligned. We align to the next largest power of 2
168 auth = kzalloc(roundup_pow_of_two(struct_size(auth, password, maxpwsize)), GFP_KERNEL);
2454a7af
NJ
169 if (!auth)
170 return ERR_PTR(-ENOMEM);
171
172 auth->version = 1;
173 auth->consumer = consumer;
2454a7af 174
3def7a3e 175 if (consumer == PLPKS_FW_OWNER || consumer == PLPKS_BOOTLOADER_OWNER)
2454a7af 176 return auth;
2454a7af
NJ
177
178 memcpy(auth->password, ospassword, ospasswordlength);
179
180 auth->passwordlength = cpu_to_be16(ospasswordlength);
181
182 return auth;
183}
184
185/**
186 * Label is combination of label attributes + name.
187 * Label attributes are used internally by kernel and not exposed to the user.
188 */
189static struct label *construct_label(char *component, u8 varos, u8 *name,
190 u16 namelen)
191{
192 struct label *label;
899d9b8f 193 size_t slen = 0;
2454a7af 194
3def7a3e 195 if (!name || namelen > PLPKS_MAX_NAME_SIZE)
2454a7af
NJ
196 return ERR_PTR(-EINVAL);
197
899d9b8f
NJ
198 // Support NULL component for signed updates
199 if (component) {
200 slen = strlen(component);
201 if (slen > sizeof(label->attr.prefix))
202 return ERR_PTR(-EINVAL);
203 }
2454a7af 204
fcf63d6b
AD
205 // The label structure must not cross a page boundary, so we align to the next power of 2
206 label = kzalloc(roundup_pow_of_two(sizeof(*label)), GFP_KERNEL);
2454a7af
NJ
207 if (!label)
208 return ERR_PTR(-ENOMEM);
209
210 if (component)
211 memcpy(&label->attr.prefix, component, slen);
212
3def7a3e 213 label->attr.version = PLPKS_LABEL_VERSION;
2454a7af 214 label->attr.os = varos;
3def7a3e 215 label->attr.length = PLPKS_MAX_LABEL_ATTR_SIZE;
2454a7af
NJ
216 memcpy(&label->name, name, namelen);
217
218 label->size = sizeof(struct label_attr) + namelen;
219
220 return label;
221}
222
223static int _plpks_get_config(void)
224{
225 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
119da30d 226 struct config {
2454a7af
NJ
227 u8 version;
228 u8 flags;
119da30d
NJ
229 __be16 rsvd0;
230 __be16 objoverhead;
2454a7af
NJ
231 __be16 maxpwsize;
232 __be16 maxobjlabelsize;
233 __be16 maxobjsize;
234 __be32 totalsize;
235 __be32 usedspace;
236 __be32 supportedpolicies;
119da30d
NJ
237 __be32 maxlargeobjectsize;
238 __be64 signedupdatealgorithms;
239 u8 rsvd1[476];
240 } __packed * config;
2454a7af 241 size_t size;
119da30d
NJ
242 int rc = 0;
243
244 size = sizeof(*config);
245
246 // Config struct must not cross a page boundary. So long as the struct
247 // size is a power of 2, this should be fine as alignment is guaranteed
248 config = kzalloc(size, GFP_KERNEL);
249 if (!config) {
250 rc = -ENOMEM;
251 goto err;
252 }
253
254 rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(config), size);
255
256 if (rc != H_SUCCESS) {
257 rc = pseries_status_to_err(rc);
258 goto err;
259 }
260
261 version = config->version;
262 objoverhead = be16_to_cpu(config->objoverhead);
263 maxpwsize = be16_to_cpu(config->maxpwsize);
264 maxobjsize = be16_to_cpu(config->maxobjsize);
265 maxobjlabelsize = be16_to_cpu(config->maxobjlabelsize);
266 totalsize = be32_to_cpu(config->totalsize);
267 usedspace = be32_to_cpu(config->usedspace);
268 supportedpolicies = be32_to_cpu(config->supportedpolicies);
269 maxlargeobjectsize = be32_to_cpu(config->maxlargeobjectsize);
270 signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms);
271
272 // Validate that the numbers we get back match the requirements of the spec
273 if (maxpwsize < 32) {
274 pr_err("Invalid Max Password Size received from hypervisor (%d < 32)\n", maxpwsize);
275 rc = -EIO;
276 goto err;
277 }
278
279 if (maxobjlabelsize < 255) {
280 pr_err("Invalid Max Object Label Size received from hypervisor (%d < 255)\n",
281 maxobjlabelsize);
282 rc = -EIO;
283 goto err;
284 }
285
286 if (totalsize < 4096) {
287 pr_err("Invalid Total Size received from hypervisor (%d < 4096)\n", totalsize);
288 rc = -EIO;
289 goto err;
290 }
291
292 if (version >= 3 && maxlargeobjectsize >= 65536 && maxobjsize != 0xFFFF) {
293 pr_err("Invalid Max Object Size (0x%x != 0xFFFF)\n", maxobjsize);
294 rc = -EIO;
295 goto err;
296 }
297
298err:
299 kfree(config);
300 return rc;
301}
302
303u8 plpks_get_version(void)
304{
305 return version;
306}
307
308u16 plpks_get_objoverhead(void)
309{
310 return objoverhead;
311}
312
313u16 plpks_get_maxpwsize(void)
314{
315 return maxpwsize;
316}
317
318u16 plpks_get_maxobjectsize(void)
319{
320 return maxobjsize;
321}
322
323u16 plpks_get_maxobjectlabelsize(void)
324{
325 return maxobjlabelsize;
326}
327
328u32 plpks_get_totalsize(void)
329{
330 return totalsize;
331}
332
333u32 plpks_get_usedspace(void)
334{
335 // Unlike other config values, usedspace regularly changes as objects
336 // are updated, so we need to refresh.
337 int rc = _plpks_get_config();
338 if (rc) {
339 pr_err("Couldn't get config, rc: %d\n", rc);
340 return 0;
341 }
342 return usedspace;
343}
344
345u32 plpks_get_supportedpolicies(void)
346{
347 return supportedpolicies;
348}
2454a7af 349
119da30d
NJ
350u32 plpks_get_maxlargeobjectsize(void)
351{
352 return maxlargeobjectsize;
353}
2454a7af 354
119da30d
NJ
355u64 plpks_get_signedupdatealgorithms(void)
356{
357 return signedupdatealgorithms;
358}
2454a7af 359
119da30d
NJ
360bool plpks_is_available(void)
361{
362 int rc;
2454a7af 363
119da30d
NJ
364 rc = _plpks_get_config();
365 if (rc)
366 return false;
2454a7af 367
119da30d 368 return true;
2454a7af
NJ
369}
370
371static int plpks_confirm_object_flushed(struct label *label,
372 struct plpks_auth *auth)
373{
374 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
f74dcbfd 375 bool timed_out = true;
2454a7af
NJ
376 u64 timeout = 0;
377 u8 status;
378 int rc;
379
380 do {
381 rc = plpar_hcall(H_PKS_CONFIRM_OBJECT_FLUSHED, retbuf,
382 virt_to_phys(auth), virt_to_phys(label),
383 label->size);
384
385 status = retbuf[0];
386 if (rc) {
f74dcbfd 387 timed_out = false;
2454a7af
NJ
388 if (rc == H_NOT_FOUND && status == 1)
389 rc = 0;
390 break;
391 }
392
f74dcbfd
AD
393 if (!rc && status == 1) {
394 timed_out = false;
2454a7af 395 break;
f74dcbfd 396 }
2454a7af 397
3def7a3e
RC
398 usleep_range(PLPKS_FLUSH_SLEEP,
399 PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
400 timeout = timeout + PLPKS_FLUSH_SLEEP;
401 } while (timeout < PLPKS_MAX_TIMEOUT);
2454a7af 402
f74dcbfd
AD
403 if (timed_out)
404 return -ETIMEDOUT;
2454a7af 405
f74dcbfd 406 return pseries_status_to_err(rc);
2454a7af
NJ
407}
408
899d9b8f
NJ
409int plpks_signed_update_var(struct plpks_var *var, u64 flags)
410{
411 unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
412 int rc;
413 struct label *label;
414 struct plpks_auth *auth;
415 u64 continuetoken = 0;
416 u64 timeout = 0;
417
418 if (!var->data || var->datalen <= 0 || var->namelen > PLPKS_MAX_NAME_SIZE)
419 return -EINVAL;
420
421 if (!(var->policy & PLPKS_SIGNEDUPDATE))
422 return -EINVAL;
423
424 // Signed updates need the component to be NULL.
425 if (var->component)
426 return -EINVAL;
427
428 auth = construct_auth(PLPKS_OS_OWNER);
429 if (IS_ERR(auth))
430 return PTR_ERR(auth);
431
432 label = construct_label(var->component, var->os, var->name, var->namelen);
433 if (IS_ERR(label)) {
434 rc = PTR_ERR(label);
435 goto out;
436 }
437
438 do {
439 rc = plpar_hcall9(H_PKS_SIGNED_UPDATE, retbuf,
440 virt_to_phys(auth), virt_to_phys(label),
441 label->size, var->policy, flags,
442 virt_to_phys(var->data), var->datalen,
443 continuetoken);
444
445 continuetoken = retbuf[0];
446 if (pseries_status_to_err(rc) == -EBUSY) {
447 int delay_ms = get_longbusy_msecs(rc);
448 mdelay(delay_ms);
449 timeout += delay_ms;
450 }
451 rc = pseries_status_to_err(rc);
452 } while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT);
453
454 if (!rc)
455 rc = plpks_confirm_object_flushed(label, auth);
456
457 kfree(label);
458out:
459 kfree(auth);
460
461 return rc;
462}
463
2454a7af
NJ
464int plpks_write_var(struct plpks_var var)
465{
466 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
467 struct plpks_auth *auth;
468 struct label *label;
469 int rc;
470
471 if (!var.component || !var.data || var.datalen <= 0 ||
3def7a3e 472 var.namelen > PLPKS_MAX_NAME_SIZE || var.datalen > PLPKS_MAX_DATA_SIZE)
2454a7af
NJ
473 return -EINVAL;
474
3def7a3e 475 if (var.policy & PLPKS_SIGNEDUPDATE)
2454a7af
NJ
476 return -EINVAL;
477
3def7a3e 478 auth = construct_auth(PLPKS_OS_OWNER);
2454a7af
NJ
479 if (IS_ERR(auth))
480 return PTR_ERR(auth);
481
482 label = construct_label(var.component, var.os, var.name, var.namelen);
483 if (IS_ERR(label)) {
484 rc = PTR_ERR(label);
485 goto out;
486 }
487
488 rc = plpar_hcall(H_PKS_WRITE_OBJECT, retbuf, virt_to_phys(auth),
489 virt_to_phys(label), label->size, var.policy,
490 virt_to_phys(var.data), var.datalen);
491
492 if (!rc)
493 rc = plpks_confirm_object_flushed(label, auth);
494
2454a7af
NJ
495 rc = pseries_status_to_err(rc);
496 kfree(label);
497out:
498 kfree(auth);
499
500 return rc;
501}
502
503int plpks_remove_var(char *component, u8 varos, struct plpks_var_name vname)
504{
505 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
506 struct plpks_auth *auth;
507 struct label *label;
508 int rc;
509
899d9b8f 510 if (vname.namelen > PLPKS_MAX_NAME_SIZE)
2454a7af
NJ
511 return -EINVAL;
512
3def7a3e 513 auth = construct_auth(PLPKS_OS_OWNER);
2454a7af
NJ
514 if (IS_ERR(auth))
515 return PTR_ERR(auth);
516
517 label = construct_label(component, varos, vname.name, vname.namelen);
518 if (IS_ERR(label)) {
519 rc = PTR_ERR(label);
520 goto out;
521 }
522
523 rc = plpar_hcall(H_PKS_REMOVE_OBJECT, retbuf, virt_to_phys(auth),
524 virt_to_phys(label), label->size);
525
526 if (!rc)
527 rc = plpks_confirm_object_flushed(label, auth);
528
2454a7af
NJ
529 rc = pseries_status_to_err(rc);
530 kfree(label);
531out:
532 kfree(auth);
533
534 return rc;
535}
536
537static int plpks_read_var(u8 consumer, struct plpks_var *var)
538{
539 unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
540 struct plpks_auth *auth;
1f622f3f 541 struct label *label = NULL;
2454a7af
NJ
542 u8 *output;
543 int rc;
544
3def7a3e 545 if (var->namelen > PLPKS_MAX_NAME_SIZE)
2454a7af
NJ
546 return -EINVAL;
547
1f622f3f 548 auth = construct_auth(consumer);
2454a7af
NJ
549 if (IS_ERR(auth))
550 return PTR_ERR(auth);
551
3def7a3e 552 if (consumer == PLPKS_OS_OWNER) {
1f622f3f
NJ
553 label = construct_label(var->component, var->os, var->name,
554 var->namelen);
555 if (IS_ERR(label)) {
556 rc = PTR_ERR(label);
557 goto out_free_auth;
558 }
2454a7af
NJ
559 }
560
561 output = kzalloc(maxobjsize, GFP_KERNEL);
562 if (!output) {
563 rc = -ENOMEM;
564 goto out_free_label;
565 }
566
3def7a3e 567 if (consumer == PLPKS_OS_OWNER)
1f622f3f
NJ
568 rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth),
569 virt_to_phys(label), label->size, virt_to_phys(output),
570 maxobjsize);
571 else
572 rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth),
573 virt_to_phys(var->name), var->namelen, virt_to_phys(output),
574 maxobjsize);
575
2454a7af
NJ
576
577 if (rc != H_SUCCESS) {
2454a7af
NJ
578 rc = pseries_status_to_err(rc);
579 goto out_free_output;
580 }
581
582 if (var->datalen == 0 || var->datalen > retbuf[0])
583 var->datalen = retbuf[0];
584
585 var->data = kzalloc(var->datalen, GFP_KERNEL);
586 if (!var->data) {
587 rc = -ENOMEM;
588 goto out_free_output;
589 }
590 var->policy = retbuf[1];
591
592 memcpy(var->data, output, var->datalen);
593 rc = 0;
594
595out_free_output:
596 kfree(output);
597out_free_label:
598 kfree(label);
599out_free_auth:
600 kfree(auth);
601
602 return rc;
603}
604
605int plpks_read_os_var(struct plpks_var *var)
606{
3def7a3e 607 return plpks_read_var(PLPKS_OS_OWNER, var);
2454a7af
NJ
608}
609
610int plpks_read_fw_var(struct plpks_var *var)
611{
3def7a3e 612 return plpks_read_var(PLPKS_FW_OWNER, var);
2454a7af
NJ
613}
614
615int plpks_read_bootloader_var(struct plpks_var *var)
616{
3def7a3e 617 return plpks_read_var(PLPKS_BOOTLOADER_OWNER, var);
2454a7af
NJ
618}
619
620static __init int pseries_plpks_init(void)
621{
622 int rc;
623
624 rc = _plpks_get_config();
625
626 if (rc) {
627 pr_err("POWER LPAR Platform KeyStore is not supported or enabled\n");
628 return rc;
629 }
630
631 rc = plpks_gen_password();
632 if (rc)
633 pr_err("Failed setting POWER LPAR Platform KeyStore Password\n");
634 else
635 pr_info("POWER LPAR Platform KeyStore initialized successfully\n");
636
637 return rc;
638}
a66de528 639machine_arch_initcall(pseries, pseries_plpks_init);