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
29
32
/* Number of bytes needed by cmd_finalize. */
30
33
#define CMD_FINALIZE_BYTES_NEEDED 7
31
34
35
+ static struct key * sed_opal_keyring ;
36
+
32
37
struct opal_step {
33
38
int (* fn )(struct opal_dev * dev , void * data );
34
39
void * data ;
@@ -269,6 +274,101 @@ static void print_buffer(const u8 *ptr, u32 length)
269
274
#endif
270
275
}
271
276
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
+
272
372
static bool check_tper (const void * data )
273
373
{
274
374
const struct d0_tper_features * tper = data ;
@@ -2459,6 +2559,9 @@ static int opal_secure_erase_locking_range(struct opal_dev *dev,
2459
2559
};
2460
2560
int ret ;
2461
2561
2562
+ ret = opal_get_key (dev , & opal_session -> opal_key );
2563
+ if (ret )
2564
+ return ret ;
2462
2565
mutex_lock (& dev -> dev_lock );
2463
2566
setup_opal_dev (dev );
2464
2567
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)
2492
2595
};
2493
2596
int ret ;
2494
2597
2598
+ ret = opal_get_key (dev , & rev -> key );
2599
+ if (ret )
2600
+ return ret ;
2495
2601
mutex_lock (& dev -> dev_lock );
2496
2602
setup_opal_dev (dev );
2497
2603
ret = execute_steps (dev , steps , ARRAY_SIZE (steps ));
@@ -2510,6 +2616,9 @@ static int opal_erase_locking_range(struct opal_dev *dev,
2510
2616
};
2511
2617
int ret ;
2512
2618
2619
+ ret = opal_get_key (dev , & opal_session -> opal_key );
2620
+ if (ret )
2621
+ return ret ;
2513
2622
mutex_lock (& dev -> dev_lock );
2514
2623
setup_opal_dev (dev );
2515
2624
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,
2538
2647
opal_mbr -> enable_disable != OPAL_MBR_DISABLE )
2539
2648
return - EINVAL ;
2540
2649
2650
+ ret = opal_get_key (dev , & opal_mbr -> key );
2651
+ if (ret )
2652
+ return ret ;
2541
2653
mutex_lock (& dev -> dev_lock );
2542
2654
setup_opal_dev (dev );
2543
2655
ret = execute_steps (dev , mbr_steps , ARRAY_SIZE (mbr_steps ));
@@ -2563,6 +2675,9 @@ static int opal_set_mbr_done(struct opal_dev *dev,
2563
2675
mbr_done -> done_flag != OPAL_MBR_NOT_DONE )
2564
2676
return - EINVAL ;
2565
2677
2678
+ ret = opal_get_key (dev , & mbr_done -> key );
2679
+ if (ret )
2680
+ return ret ;
2566
2681
mutex_lock (& dev -> dev_lock );
2567
2682
setup_opal_dev (dev );
2568
2683
ret = execute_steps (dev , mbr_steps , ARRAY_SIZE (mbr_steps ));
@@ -2584,6 +2699,9 @@ static int opal_write_shadow_mbr(struct opal_dev *dev,
2584
2699
if (info -> size == 0 )
2585
2700
return 0 ;
2586
2701
2702
+ ret = opal_get_key (dev , & info -> key );
2703
+ if (ret )
2704
+ return ret ;
2587
2705
mutex_lock (& dev -> dev_lock );
2588
2706
setup_opal_dev (dev );
2589
2707
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,
2641
2759
return - EINVAL ;
2642
2760
}
2643
2761
2762
+ ret = opal_get_key (dev , & lk_unlk -> session .opal_key );
2763
+ if (ret )
2764
+ return ret ;
2644
2765
mutex_lock (& dev -> dev_lock );
2645
2766
setup_opal_dev (dev );
2646
2767
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
2663
2784
2664
2785
int ret ;
2665
2786
2787
+ ret = opal_get_key (dev , opal );
2788
+
2789
+ if (ret )
2790
+ return ret ;
2666
2791
mutex_lock (& dev -> dev_lock );
2667
2792
setup_opal_dev (dev );
2668
2793
if (psid )
@@ -2763,6 +2888,9 @@ static int opal_lock_unlock(struct opal_dev *dev,
2763
2888
if (lk_unlk -> session .who > OPAL_USER9 )
2764
2889
return - EINVAL ;
2765
2890
2891
+ ret = opal_get_key (dev , & lk_unlk -> session .opal_key );
2892
+ if (ret )
2893
+ return ret ;
2766
2894
mutex_lock (& dev -> dev_lock );
2767
2895
opal_lock_check_for_saved_key (dev , lk_unlk );
2768
2896
ret = __opal_lock_unlock (dev , lk_unlk );
@@ -2786,6 +2914,9 @@ static int opal_take_ownership(struct opal_dev *dev, struct opal_key *opal)
2786
2914
if (!dev )
2787
2915
return - ENODEV ;
2788
2916
2917
+ ret = opal_get_key (dev , opal );
2918
+ if (ret )
2919
+ return ret ;
2789
2920
mutex_lock (& dev -> dev_lock );
2790
2921
setup_opal_dev (dev );
2791
2922
ret = execute_steps (dev , owner_steps , ARRAY_SIZE (owner_steps ));
@@ -2808,6 +2939,9 @@ static int opal_activate_lsp(struct opal_dev *dev,
2808
2939
if (!opal_lr_act -> num_lrs || opal_lr_act -> num_lrs > OPAL_MAX_LRS )
2809
2940
return - EINVAL ;
2810
2941
2942
+ ret = opal_get_key (dev , & opal_lr_act -> key );
2943
+ if (ret )
2944
+ return ret ;
2811
2945
mutex_lock (& dev -> dev_lock );
2812
2946
setup_opal_dev (dev );
2813
2947
ret = execute_steps (dev , active_steps , ARRAY_SIZE (active_steps ));
@@ -2826,6 +2960,9 @@ static int opal_setup_locking_range(struct opal_dev *dev,
2826
2960
};
2827
2961
int ret ;
2828
2962
2963
+ ret = opal_get_key (dev , & opal_lrs -> session .opal_key );
2964
+ if (ret )
2965
+ return ret ;
2829
2966
mutex_lock (& dev -> dev_lock );
2830
2967
setup_opal_dev (dev );
2831
2968
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)
2879
3016
ret = execute_steps (dev , pw_steps , ARRAY_SIZE (pw_steps ));
2880
3017
mutex_unlock (& dev -> dev_lock );
2881
3018
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
+
2882
3027
return ret ;
2883
3028
}
2884
3029
@@ -2899,6 +3044,9 @@ static int opal_activate_user(struct opal_dev *dev,
2899
3044
return - EINVAL ;
2900
3045
}
2901
3046
3047
+ ret = opal_get_key (dev , & opal_session -> opal_key );
3048
+ if (ret )
3049
+ return ret ;
2902
3050
mutex_lock (& dev -> dev_lock );
2903
3051
setup_opal_dev (dev );
2904
3052
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,
2985
3133
{
2986
3134
int ret , bit_set ;
2987
3135
3136
+ ret = opal_get_key (dev , & rw_tbl -> key );
3137
+ if (ret )
3138
+ return ret ;
2988
3139
mutex_lock (& dev -> dev_lock );
2989
3140
setup_opal_dev (dev );
2990
3141
@@ -3053,9 +3204,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
3053
3204
if (!capable (CAP_SYS_ADMIN ))
3054
3205
return - EACCES ;
3055
3206
if (!dev )
3056
- return - ENOTSUPP ;
3207
+ return - EOPNOTSUPP ;
3057
3208
if (!(dev -> flags & OPAL_FL_SUPPORTED ))
3058
- return - ENOTSUPP ;
3209
+ return - EOPNOTSUPP ;
3059
3210
3060
3211
if (cmd & IOC_IN ) {
3061
3212
p = memdup_user (arg , _IOC_SIZE (cmd ));
@@ -3137,3 +3288,22 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
3137
3288
return ret ;
3138
3289
}
3139
3290
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 );
0 commit comments