Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Greg Joyce and committed by
Jens Axboe
3bfeb612 5c82efc1

+184 -3
+2
block/Kconfig
··· 184 184 185 185 config BLK_SED_OPAL 186 186 bool "Logic for interfacing with Opal enabled SEDs" 187 + depends on KEYS 188 + select PSERIES_PLPKS if PPC_PSERIES 187 189 help 188 190 Builds Logic for interfacing with Opal enabled controllers. 189 191 Enabling this option enables users to setup/unlock/lock
+172 -2
block/sed-opal.c
··· 20 20 #include <linux/sed-opal.h> 21 21 #include <linux/string.h> 22 22 #include <linux/kdev_t.h> 23 + #include <linux/key.h> 24 + #include <linux/key-type.h> 25 + #include <keys/user-type.h> 23 26 24 27 #include "opal_proto.h" 25 28 ··· 31 28 32 29 /* Number of bytes needed by cmd_finalize. */ 33 30 #define CMD_FINALIZE_BYTES_NEEDED 7 31 + 32 + static struct key *sed_opal_keyring; 34 33 35 34 struct opal_step { 36 35 int (*fn)(struct opal_dev *dev, void *data); ··· 272 267 print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length); 273 268 pr_debug("\n"); 274 269 #endif 270 + } 271 + 272 + /* 273 + * Allocate/update a SED Opal key and add it to the SED Opal keyring. 274 + */ 275 + static int update_sed_opal_key(const char *desc, u_char *key_data, int keylen) 276 + { 277 + key_ref_t kr; 278 + 279 + if (!sed_opal_keyring) 280 + return -ENOKEY; 281 + 282 + kr = key_create_or_update(make_key_ref(sed_opal_keyring, true), "user", 283 + desc, (const void *)key_data, keylen, 284 + KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_WRITE, 285 + KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN | 286 + KEY_ALLOC_BYPASS_RESTRICTION); 287 + if (IS_ERR(kr)) { 288 + pr_err("Error adding SED key (%ld)\n", PTR_ERR(kr)); 289 + return PTR_ERR(kr); 290 + } 291 + 292 + return 0; 293 + } 294 + 295 + /* 296 + * Read a SED Opal key from the SED Opal keyring. 297 + */ 298 + static int read_sed_opal_key(const char *key_name, u_char *buffer, int buflen) 299 + { 300 + int ret; 301 + key_ref_t kref; 302 + struct key *key; 303 + 304 + if (!sed_opal_keyring) 305 + return -ENOKEY; 306 + 307 + kref = keyring_search(make_key_ref(sed_opal_keyring, true), 308 + &key_type_user, key_name, true); 309 + 310 + if (IS_ERR(kref)) 311 + ret = PTR_ERR(kref); 312 + 313 + key = key_ref_to_ptr(kref); 314 + down_read(&key->sem); 315 + ret = key_validate(key); 316 + if (ret == 0) { 317 + if (buflen > key->datalen) 318 + buflen = key->datalen; 319 + 320 + ret = key->type->read(key, (char *)buffer, buflen); 321 + } 322 + up_read(&key->sem); 323 + 324 + key_ref_put(kref); 325 + 326 + return ret; 327 + } 328 + 329 + static int opal_get_key(struct opal_dev *dev, struct opal_key *key) 330 + { 331 + int ret = 0; 332 + 333 + switch (key->key_type) { 334 + case OPAL_INCLUDED: 335 + /* the key is ready to use */ 336 + break; 337 + case OPAL_KEYRING: 338 + /* the key is in the keyring */ 339 + ret = read_sed_opal_key(OPAL_AUTH_KEY, key->key, OPAL_KEY_MAX); 340 + if (ret > 0) { 341 + if (ret > U8_MAX) { 342 + ret = -ENOSPC; 343 + goto error; 344 + } 345 + key->key_len = ret; 346 + key->key_type = OPAL_INCLUDED; 347 + } 348 + break; 349 + default: 350 + ret = -EINVAL; 351 + break; 352 + } 353 + if (ret < 0) 354 + goto error; 355 + 356 + /* must have a PEK by now or it's an error */ 357 + if (key->key_type != OPAL_INCLUDED || key->key_len == 0) { 358 + ret = -EINVAL; 359 + goto error; 360 + } 361 + return 0; 362 + error: 363 + pr_debug("Error getting password: %d\n", ret); 364 + return ret; 275 365 } 276 366 277 367 static bool check_tper(const void *data) ··· 2559 2459 }; 2560 2460 int ret; 2561 2461 2462 + ret = opal_get_key(dev, &opal_session->opal_key); 2463 + if (ret) 2464 + return ret; 2562 2465 mutex_lock(&dev->dev_lock); 2563 2466 setup_opal_dev(dev); 2564 2467 ret = execute_steps(dev, erase_steps, ARRAY_SIZE(erase_steps)); ··· 2595 2492 }; 2596 2493 int ret; 2597 2494 2495 + ret = opal_get_key(dev, &rev->key); 2496 + if (ret) 2497 + return ret; 2598 2498 mutex_lock(&dev->dev_lock); 2599 2499 setup_opal_dev(dev); 2600 2500 ret = execute_steps(dev, steps, ARRAY_SIZE(steps)); ··· 2616 2510 }; 2617 2511 int ret; 2618 2512 2513 + ret = opal_get_key(dev, &opal_session->opal_key); 2514 + if (ret) 2515 + return ret; 2619 2516 mutex_lock(&dev->dev_lock); 2620 2517 setup_opal_dev(dev); 2621 2518 ret = execute_steps(dev, erase_steps, ARRAY_SIZE(erase_steps)); ··· 2647 2538 opal_mbr->enable_disable != OPAL_MBR_DISABLE) 2648 2539 return -EINVAL; 2649 2540 2541 + ret = opal_get_key(dev, &opal_mbr->key); 2542 + if (ret) 2543 + return ret; 2650 2544 mutex_lock(&dev->dev_lock); 2651 2545 setup_opal_dev(dev); 2652 2546 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps)); ··· 2675 2563 mbr_done->done_flag != OPAL_MBR_NOT_DONE) 2676 2564 return -EINVAL; 2677 2565 2566 + ret = opal_get_key(dev, &mbr_done->key); 2567 + if (ret) 2568 + return ret; 2678 2569 mutex_lock(&dev->dev_lock); 2679 2570 setup_opal_dev(dev); 2680 2571 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps)); ··· 2699 2584 if (info->size == 0) 2700 2585 return 0; 2701 2586 2587 + ret = opal_get_key(dev, &info->key); 2588 + if (ret) 2589 + return ret; 2702 2590 mutex_lock(&dev->dev_lock); 2703 2591 setup_opal_dev(dev); 2704 2592 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps)); ··· 2759 2641 return -EINVAL; 2760 2642 } 2761 2643 2644 + ret = opal_get_key(dev, &lk_unlk->session.opal_key); 2645 + if (ret) 2646 + return ret; 2762 2647 mutex_lock(&dev->dev_lock); 2763 2648 setup_opal_dev(dev); 2764 2649 ret = execute_steps(dev, steps, ARRAY_SIZE(steps)); ··· 2784 2663 2785 2664 int ret; 2786 2665 2666 + ret = opal_get_key(dev, opal); 2667 + 2668 + if (ret) 2669 + return ret; 2787 2670 mutex_lock(&dev->dev_lock); 2788 2671 setup_opal_dev(dev); 2789 2672 if (psid) ··· 2888 2763 if (lk_unlk->session.who > OPAL_USER9) 2889 2764 return -EINVAL; 2890 2765 2766 + ret = opal_get_key(dev, &lk_unlk->session.opal_key); 2767 + if (ret) 2768 + return ret; 2891 2769 mutex_lock(&dev->dev_lock); 2892 2770 opal_lock_check_for_saved_key(dev, lk_unlk); 2893 2771 ret = __opal_lock_unlock(dev, lk_unlk); ··· 2914 2786 if (!dev) 2915 2787 return -ENODEV; 2916 2788 2789 + ret = opal_get_key(dev, opal); 2790 + if (ret) 2791 + return ret; 2917 2792 mutex_lock(&dev->dev_lock); 2918 2793 setup_opal_dev(dev); 2919 2794 ret = execute_steps(dev, owner_steps, ARRAY_SIZE(owner_steps)); ··· 2939 2808 if (!opal_lr_act->num_lrs || opal_lr_act->num_lrs > OPAL_MAX_LRS) 2940 2809 return -EINVAL; 2941 2810 2811 + ret = opal_get_key(dev, &opal_lr_act->key); 2812 + if (ret) 2813 + return ret; 2942 2814 mutex_lock(&dev->dev_lock); 2943 2815 setup_opal_dev(dev); 2944 2816 ret = execute_steps(dev, active_steps, ARRAY_SIZE(active_steps)); ··· 2960 2826 }; 2961 2827 int ret; 2962 2828 2829 + ret = opal_get_key(dev, &opal_lrs->session.opal_key); 2830 + if (ret) 2831 + return ret; 2963 2832 mutex_lock(&dev->dev_lock); 2964 2833 setup_opal_dev(dev); 2965 2834 ret = execute_steps(dev, lr_steps, ARRAY_SIZE(lr_steps)); ··· 3016 2879 ret = execute_steps(dev, pw_steps, ARRAY_SIZE(pw_steps)); 3017 2880 mutex_unlock(&dev->dev_lock); 3018 2881 2882 + if (ret) 2883 + return ret; 2884 + 2885 + /* update keyring with new password */ 2886 + ret = update_sed_opal_key(OPAL_AUTH_KEY, 2887 + opal_pw->new_user_pw.opal_key.key, 2888 + opal_pw->new_user_pw.opal_key.key_len); 2889 + 3019 2890 return ret; 3020 2891 } 3021 2892 ··· 3044 2899 return -EINVAL; 3045 2900 } 3046 2901 2902 + ret = opal_get_key(dev, &opal_session->opal_key); 2903 + if (ret) 2904 + return ret; 3047 2905 mutex_lock(&dev->dev_lock); 3048 2906 setup_opal_dev(dev); 3049 2907 ret = execute_steps(dev, act_steps, ARRAY_SIZE(act_steps)); ··· 3133 2985 { 3134 2986 int ret, bit_set; 3135 2987 2988 + ret = opal_get_key(dev, &rw_tbl->key); 2989 + if (ret) 2990 + return ret; 3136 2991 mutex_lock(&dev->dev_lock); 3137 2992 setup_opal_dev(dev); 3138 2993 ··· 3204 3053 if (!capable(CAP_SYS_ADMIN)) 3205 3054 return -EACCES; 3206 3055 if (!dev) 3207 - return -ENOTSUPP; 3056 + return -EOPNOTSUPP; 3208 3057 if (!(dev->flags & OPAL_FL_SUPPORTED)) 3209 - return -ENOTSUPP; 3058 + return -EOPNOTSUPP; 3210 3059 3211 3060 if (cmd & IOC_IN) { 3212 3061 p = memdup_user(arg, _IOC_SIZE(cmd)); ··· 3288 3137 return ret; 3289 3138 } 3290 3139 EXPORT_SYMBOL_GPL(sed_ioctl); 3140 + 3141 + static int __init sed_opal_init(void) 3142 + { 3143 + struct key *kr; 3144 + 3145 + kr = keyring_alloc(".sed_opal", 3146 + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), 3147 + (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | 3148 + KEY_USR_READ | KEY_USR_SEARCH | KEY_USR_WRITE, 3149 + KEY_ALLOC_NOT_IN_QUOTA, 3150 + NULL, NULL); 3151 + if (IS_ERR(kr)) 3152 + return PTR_ERR(kr); 3153 + 3154 + sed_opal_keyring = kr; 3155 + 3156 + return 0; 3157 + } 3158 + late_initcall(sed_opal_init);
+3
include/linux/sed-opal.h
··· 25 25 struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv); 26 26 int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *ioctl_ptr); 27 27 28 + #define OPAL_AUTH_KEY "opal-boot-pin" 29 + #define OPAL_AUTH_KEY_PREV "opal-boot-pin-prev" 30 + 28 31 static inline bool is_sed_ioctl(unsigned int cmd) 29 32 { 30 33 switch (cmd) {
+7 -1
include/uapi/linux/sed-opal.h
··· 49 49 OPAL_SAVE_FOR_LOCK = 0x01, 50 50 }; 51 51 52 + enum opal_key_type { 53 + OPAL_INCLUDED = 0, /* key[] is the key */ 54 + OPAL_KEYRING, /* key is in keyring */ 55 + }; 56 + 52 57 struct opal_key { 53 58 __u8 lr; 54 59 __u8 key_len; 55 - __u8 __align[6]; 60 + __u8 key_type; 61 + __u8 __align[5]; 56 62 __u8 key[OPAL_KEY_MAX]; 57 63 }; 58 64