Skip to content

Commit 3bfeb61

Browse files
Greg Joyceaxboe
authored andcommitted
block: sed-opal: keyring support for SED keys
Extend the SED block driver so it can alternatively obtain a key from a sed-opal kernel keyring. The SED ioctls will indicate the source of the key, either directly in the ioctl data or from the keyring. This allows the use of SED commands in scripts such as udev scripts so that drives may be automatically unlocked as they become available. Signed-off-by: Greg Joyce <gjoyce@linux.vnet.ibm.com> Reviewed-by: Jonathan Derrick <jonathan.derrick@linux.dev> Acked-by: Jarkko Sakkinen <jarkko@kernel.org> Link: https://lore.kernel.org/r/20230721211534.3437070-4-gjoyce@linux.vnet.ibm.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 5c82efc commit 3bfeb61

File tree

4 files changed

+184
-3
lines changed

4 files changed

+184
-3
lines changed

block/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ config BLK_DEBUG_FS_ZONED
184184

185185
config BLK_SED_OPAL
186186
bool "Logic for interfacing with Opal enabled SEDs"
187+
depends on KEYS
188+
select PSERIES_PLPKS if PPC_PSERIES
187189
help
188190
Builds Logic for interfacing with Opal enabled controllers.
189191
Enabling this option enables users to setup/unlock/lock

block/sed-opal.c

Lines changed: 172 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include <linux/sed-opal.h>
2121
#include <linux/string.h>
2222
#include <linux/kdev_t.h>
23+
#include <linux/key.h>
24+
#include <linux/key-type.h>
25+
#include <keys/user-type.h>
2326

2427
#include "opal_proto.h"
2528

@@ -29,6 +32,8 @@
2932
/* Number of bytes needed by cmd_finalize. */
3033
#define CMD_FINALIZE_BYTES_NEEDED 7
3134

35+
static struct key *sed_opal_keyring;
36+
3237
struct opal_step {
3338
int (*fn)(struct opal_dev *dev, void *data);
3439
void *data;
@@ -269,6 +274,101 @@ static void print_buffer(const u8 *ptr, u32 length)
269274
#endif
270275
}
271276

277+
/*
278+
* Allocate/update a SED Opal key and add it to the SED Opal keyring.
279+
*/
280+
static int update_sed_opal_key(const char *desc, u_char *key_data, int keylen)
281+
{
282+
key_ref_t kr;
283+
284+
if (!sed_opal_keyring)
285+
return -ENOKEY;
286+
287+
kr = key_create_or_update(make_key_ref(sed_opal_keyring, true), "user",
288+
desc, (const void *)key_data, keylen,
289+
KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_WRITE,
290+
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN |
291+
KEY_ALLOC_BYPASS_RESTRICTION);
292+
if (IS_ERR(kr)) {
293+
pr_err("Error adding SED key (%ld)\n", PTR_ERR(kr));
294+
return PTR_ERR(kr);
295+
}
296+
297+
return 0;
298+
}
299+
300+
/*
301+
* Read a SED Opal key from the SED Opal keyring.
302+
*/
303+
static int read_sed_opal_key(const char *key_name, u_char *buffer, int buflen)
304+
{
305+
int ret;
306+
key_ref_t kref;
307+
struct key *key;
308+
309+
if (!sed_opal_keyring)
310+
return -ENOKEY;
311+
312+
kref = keyring_search(make_key_ref(sed_opal_keyring, true),
313+
&key_type_user, key_name, true);
314+
315+
if (IS_ERR(kref))
316+
ret = PTR_ERR(kref);
317+
318+
key = key_ref_to_ptr(kref);
319+
down_read(&key->sem);
320+
ret = key_validate(key);
321+
if (ret == 0) {
322+
if (buflen > key->datalen)
323+
buflen = key->datalen;
324+
325+
ret = key->type->read(key, (char *)buffer, buflen);
326+
}
327+
up_read(&key->sem);
328+
329+
key_ref_put(kref);
330+
331+
return ret;
332+
}
333+
334+
static int opal_get_key(struct opal_dev *dev, struct opal_key *key)
335+
{
336+
int ret = 0;
337+
338+
switch (key->key_type) {
339+
case OPAL_INCLUDED:
340+
/* the key is ready to use */
341+
break;
342+
case OPAL_KEYRING:
343+
/* the key is in the keyring */
344+
ret = read_sed_opal_key(OPAL_AUTH_KEY, key->key, OPAL_KEY_MAX);
345+
if (ret > 0) {
346+
if (ret > U8_MAX) {
347+
ret = -ENOSPC;
348+
goto error;
349+
}
350+
key->key_len = ret;
351+
key->key_type = OPAL_INCLUDED;
352+
}
353+
break;
354+
default:
355+
ret = -EINVAL;
356+
break;
357+
}
358+
if (ret < 0)
359+
goto error;
360+
361+
/* must have a PEK by now or it's an error */
362+
if (key->key_type != OPAL_INCLUDED || key->key_len == 0) {
363+
ret = -EINVAL;
364+
goto error;
365+
}
366+
return 0;
367+
error:
368+
pr_debug("Error getting password: %d\n", ret);
369+
return ret;
370+
}
371+
272372
static bool check_tper(const void *data)
273373
{
274374
const struct d0_tper_features *tper = data;
@@ -2459,6 +2559,9 @@ static int opal_secure_erase_locking_range(struct opal_dev *dev,
24592559
};
24602560
int ret;
24612561

2562+
ret = opal_get_key(dev, &opal_session->opal_key);
2563+
if (ret)
2564+
return ret;
24622565
mutex_lock(&dev->dev_lock);
24632566
setup_opal_dev(dev);
24642567
ret = execute_steps(dev, erase_steps, ARRAY_SIZE(erase_steps));
@@ -2492,6 +2595,9 @@ static int opal_revertlsp(struct opal_dev *dev, struct opal_revert_lsp *rev)
24922595
};
24932596
int ret;
24942597

2598+
ret = opal_get_key(dev, &rev->key);
2599+
if (ret)
2600+
return ret;
24952601
mutex_lock(&dev->dev_lock);
24962602
setup_opal_dev(dev);
24972603
ret = execute_steps(dev, steps, ARRAY_SIZE(steps));
@@ -2510,6 +2616,9 @@ static int opal_erase_locking_range(struct opal_dev *dev,
25102616
};
25112617
int ret;
25122618

2619+
ret = opal_get_key(dev, &opal_session->opal_key);
2620+
if (ret)
2621+
return ret;
25132622
mutex_lock(&dev->dev_lock);
25142623
setup_opal_dev(dev);
25152624
ret = execute_steps(dev, erase_steps, ARRAY_SIZE(erase_steps));
@@ -2538,6 +2647,9 @@ static int opal_enable_disable_shadow_mbr(struct opal_dev *dev,
25382647
opal_mbr->enable_disable != OPAL_MBR_DISABLE)
25392648
return -EINVAL;
25402649

2650+
ret = opal_get_key(dev, &opal_mbr->key);
2651+
if (ret)
2652+
return ret;
25412653
mutex_lock(&dev->dev_lock);
25422654
setup_opal_dev(dev);
25432655
ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
@@ -2563,6 +2675,9 @@ static int opal_set_mbr_done(struct opal_dev *dev,
25632675
mbr_done->done_flag != OPAL_MBR_NOT_DONE)
25642676
return -EINVAL;
25652677

2678+
ret = opal_get_key(dev, &mbr_done->key);
2679+
if (ret)
2680+
return ret;
25662681
mutex_lock(&dev->dev_lock);
25672682
setup_opal_dev(dev);
25682683
ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
@@ -2584,6 +2699,9 @@ static int opal_write_shadow_mbr(struct opal_dev *dev,
25842699
if (info->size == 0)
25852700
return 0;
25862701

2702+
ret = opal_get_key(dev, &info->key);
2703+
if (ret)
2704+
return ret;
25872705
mutex_lock(&dev->dev_lock);
25882706
setup_opal_dev(dev);
25892707
ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
@@ -2641,6 +2759,9 @@ static int opal_add_user_to_lr(struct opal_dev *dev,
26412759
return -EINVAL;
26422760
}
26432761

2762+
ret = opal_get_key(dev, &lk_unlk->session.opal_key);
2763+
if (ret)
2764+
return ret;
26442765
mutex_lock(&dev->dev_lock);
26452766
setup_opal_dev(dev);
26462767
ret = execute_steps(dev, steps, ARRAY_SIZE(steps));
@@ -2663,6 +2784,10 @@ static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psi
26632784

26642785
int ret;
26652786

2787+
ret = opal_get_key(dev, opal);
2788+
2789+
if (ret)
2790+
return ret;
26662791
mutex_lock(&dev->dev_lock);
26672792
setup_opal_dev(dev);
26682793
if (psid)
@@ -2763,6 +2888,9 @@ static int opal_lock_unlock(struct opal_dev *dev,
27632888
if (lk_unlk->session.who > OPAL_USER9)
27642889
return -EINVAL;
27652890

2891+
ret = opal_get_key(dev, &lk_unlk->session.opal_key);
2892+
if (ret)
2893+
return ret;
27662894
mutex_lock(&dev->dev_lock);
27672895
opal_lock_check_for_saved_key(dev, lk_unlk);
27682896
ret = __opal_lock_unlock(dev, lk_unlk);
@@ -2786,6 +2914,9 @@ static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
27862914
if (!dev)
27872915
return -ENODEV;
27882916

2917+
ret = opal_get_key(dev, opal);
2918+
if (ret)
2919+
return ret;
27892920
mutex_lock(&dev->dev_lock);
27902921
setup_opal_dev(dev);
27912922
ret = execute_steps(dev, owner_steps, ARRAY_SIZE(owner_steps));
@@ -2808,6 +2939,9 @@ static int opal_activate_lsp(struct opal_dev *dev,
28082939
if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS)
28092940
return -EINVAL;
28102941

2942+
ret = opal_get_key(dev, &opal_lr_act->key);
2943+
if (ret)
2944+
return ret;
28112945
mutex_lock(&dev->dev_lock);
28122946
setup_opal_dev(dev);
28132947
ret = execute_steps(dev, active_steps, ARRAY_SIZE(active_steps));
@@ -2826,6 +2960,9 @@ static int opal_setup_locking_range(struct opal_dev *dev,
28262960
};
28272961
int ret;
28282962

2963+
ret = opal_get_key(dev, &opal_lrs->session.opal_key);
2964+
if (ret)
2965+
return ret;
28292966
mutex_lock(&dev->dev_lock);
28302967
setup_opal_dev(dev);
28312968
ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps));
@@ -2879,6 +3016,14 @@ static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
28793016
ret = execute_steps(dev, pw_steps, ARRAY_SIZE(pw_steps));
28803017
mutex_unlock(&dev->dev_lock);
28813018

3019+
if (ret)
3020+
return ret;
3021+
3022+
/* update keyring with new password */
3023+
ret = update_sed_opal_key(OPAL_AUTH_KEY,
3024+
opal_pw->new_user_pw.opal_key.key,
3025+
opal_pw->new_user_pw.opal_key.key_len);
3026+
28823027
return ret;
28833028
}
28843029

@@ -2899,6 +3044,9 @@ static int opal_activate_user(struct opal_dev *dev,
28993044
return -EINVAL;
29003045
}
29013046

3047+
ret = opal_get_key(dev, &opal_session->opal_key);
3048+
if (ret)
3049+
return ret;
29023050
mutex_lock(&dev->dev_lock);
29033051
setup_opal_dev(dev);
29043052
ret = execute_steps(dev, act_steps, ARRAY_SIZE(act_steps));
@@ -2985,6 +3133,9 @@ static int opal_generic_read_write_table(struct opal_dev *dev,
29853133
{
29863134
int ret, bit_set;
29873135

3136+
ret = opal_get_key(dev, &rw_tbl->key);
3137+
if (ret)
3138+
return ret;
29883139
mutex_lock(&dev->dev_lock);
29893140
setup_opal_dev(dev);
29903141

@@ -3053,9 +3204,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
30533204
if (!capable(CAP_SYS_ADMIN))
30543205
return -EACCES;
30553206
if (!dev)
3056-
return -ENOTSUPP;
3207+
return -EOPNOTSUPP;
30573208
if (!(dev->flags & OPAL_FL_SUPPORTED))
3058-
return -ENOTSUPP;
3209+
return -EOPNOTSUPP;
30593210

30603211
if (cmd & IOC_IN) {
30613212
p = memdup_user(arg, _IOC_SIZE(cmd));
@@ -3137,3 +3288,22 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
31373288
return ret;
31383289
}
31393290
EXPORT_SYMBOL_GPL(sed_ioctl);
3291+
3292+
static int __init sed_opal_init(void)
3293+
{
3294+
struct key *kr;
3295+
3296+
kr = keyring_alloc(".sed_opal",
3297+
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
3298+
(KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW |
3299+
KEY_USR_READ | KEY_USR_SEARCH | KEY_USR_WRITE,
3300+
KEY_ALLOC_NOT_IN_QUOTA,
3301+
NULL, NULL);
3302+
if (IS_ERR(kr))
3303+
return PTR_ERR(kr);
3304+
3305+
sed_opal_keyring = kr;
3306+
3307+
return 0;
3308+
}
3309+
late_initcall(sed_opal_init);

include/linux/sed-opal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ bool opal_unlock_from_suspend(struct opal_dev *dev);
2525
struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv);
2626
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *ioctl_ptr);
2727

28+
#define OPAL_AUTH_KEY "opal-boot-pin"
29+
#define OPAL_AUTH_KEY_PREV "opal-boot-pin-prev"
30+
2831
static inline bool is_sed_ioctl(unsigned int cmd)
2932
{
3033
switch (cmd) {

include/uapi/linux/sed-opal.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,16 @@ enum opal_lock_flags {
4949
OPAL_SAVE_FOR_LOCK = 0x01,
5050
};
5151

52+
enum opal_key_type {
53+
OPAL_INCLUDED = 0, /* key[] is the key */
54+
OPAL_KEYRING, /* key is in keyring */
55+
};
56+
5257
struct opal_key {
5358
__u8 lr;
5459
__u8 key_len;
55-
__u8 __align[6];
60+
__u8 key_type;
61+
__u8 __align[5];
5662
__u8 key[OPAL_KEY_MAX];
5763
};
5864

0 commit comments

Comments
 (0)