Commit 00fab235 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Martin Schwidefsky

s390/zcrypt: multiple zcrypt device nodes support

This patch is an extension to the zcrypt device driver to provide,
support and maintain multiple zcrypt device nodes. The individual
zcrypt device nodes can be restricted in terms of crypto cards,
domains and available ioctls. Such a device node can be used as a
base for container solutions like docker to control and restrict
the access to crypto resources.

The handling is done with a new sysfs subdir /sys/class/zcrypt.
Echoing a name (or an empty sting) into the attribute "create" creates
a new zcrypt device node. In /sys/class/zcrypt a new link will appear
which points to the sysfs device tree of this new device. The
attribute files "ioctlmask", "apmask" and "aqmask" in this directory
are used to customize this new zcrypt device node instance. Finally
the zcrypt device node can be destroyed by echoing the name into
/sys/class/zcrypt/destroy. The internal structs holding the device
info are reference counted - so a destroy will not hard remove a
device but only marks it as removable when the reference counter drops
to zero.

The mask values are bitmaps in big endian order starting with bit 0.
So adapter number 0 is the leftmost bit, mask is 0x8000...  The sysfs
attributes accept 2 different formats:
* Absolute hex string starting with 0x like "0x12345678" does set
  the mask starting from left to right. If the given string is shorter
  than the mask it is padded with 0s on the right. If the string is
  longer than the mask an error comes back (EINVAL).
* Relative format - a concatenation (done with ',') of the
  terms +<bitnr>[-<bitnr>] or -<bitnr>[-<bitnr>]. <bitnr> may be any
  valid number (hex, decimal or octal) in the range 0...255. Here are
  some examples:
    "+0-15,+32,-128,-0xFF"
    "-0-255,+1-16,+0x128"
    "+1,+2,+3,+4,-5,-7-10"

A simple usage examples:

  # create new zcrypt device 'my_zcrypt':
  echo "my_zcrypt" >/sys/class/zcrypt/create
  # go into the device dir of this new device
  echo "my_zcrypt" >create
  cd my_zcrypt/
  ls -l
  total 0
  -rw-r--r-- 1 root root 4096 Jul 20 15:23 apmask
  -rw-r--r-- 1 root root 4096 Jul 20 15:23 aqmask
  -r--r--r-- 1 root root 4096 Jul 20 15:23 dev
  -rw-r--r-- 1 root root 4096 Jul 20 15:23 ioctlmask
  lrwxrwxrwx 1 root root    0 Jul 20 15:23 subsystem -> ../../../../class/zcrypt
  ...
  # customize this zcrypt node clone
  # enable only adapter 0 and 2
  echo "0xa0" >apmask
  # enable only domain 6
  echo "+6" >aqmask
  # enable all 256 ioctls
  echo "+0-255" >ioctls
  # now the /dev/my_zcrypt may be used
  # finally destroy it
  echo "my_zcrypt" >/sys/class/zcrypt/destroy

Please note that a very similar 'filtering behavior' also applies to
the parent z90crypt device. The two mask attributes apmask and aqmask
in /sys/bus/ap act the very same for the z90crypt device node. However
the implementation here is totally different as the ap bus acts on
bind/unbind of queue devices and associated drivers but the effect is
still the same. So there are two filters active for each additional
zcrypt device node: The adapter/domain needs to be enabled on the ap
bus level and it needs to be active on the zcrypt device node level.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent ccc413f6
......@@ -232,6 +232,7 @@ CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_ZCRYPT=m
CONFIG_ZCRYPT_MULTIDEVNODES=y
CONFIG_PKEY=m
CONFIG_CRYPTO_PAES_S390=m
CONFIG_CRYPTO_SHA1_S390=m
......
......@@ -2,9 +2,9 @@
/*
* include/asm-s390/zcrypt.h
*
* zcrypt 2.1.0 (user-visible header)
* zcrypt 2.2.0 (user-visible header)
*
* Copyright IBM Corp. 2001, 2006
* Copyright IBM Corp. 2001, 2018
* Author(s): Robert Burroughs
* Eric Rossman (edrossma@us.ibm.com)
*
......@@ -15,12 +15,15 @@
#define __ASM_S390_ZCRYPT_H
#define ZCRYPT_VERSION 2
#define ZCRYPT_RELEASE 1
#define ZCRYPT_VARIANT 1
#define ZCRYPT_RELEASE 2
#define ZCRYPT_VARIANT 0
#include <linux/ioctl.h>
#include <linux/compiler.h>
/* Name of the zcrypt device driver. */
#define ZCRYPT_NAME "zcrypt"
/**
* struct ica_rsa_modexpo
*
......@@ -309,6 +312,16 @@ struct zcrypt_device_matrix_ext {
#define ZCRYPT_QDEPTH_MASK _IOR(ZCRYPT_IOCTL_MAGIC, 0x59, char[MAX_ZDEV_CARDIDS_EXT])
#define ZCRYPT_PERDEV_REQCNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x5a, int[MAX_ZDEV_CARDIDS_EXT])
/*
* Support for multiple zcrypt device nodes.
*/
/* Nr of minor device node numbers to allocate. */
#define ZCRYPT_MAX_MINOR_NODES 256
/* Max amount of possible ioctls */
#define MAX_ZDEV_IOCTLS (1 << _IOC_NRBITS)
/*
* Only deprecated defines, structs and ioctls below this line.
*/
......
......@@ -73,6 +73,17 @@ config ZCRYPT
+ Crypto Express 2,3,4 or 5 Accelerator (CEXxA)
+ Crypto Express 4 or 5 EP11 Coprocessor (CEXxP)
config ZCRYPT_MULTIDEVNODES
bool "Support for multiple zcrypt device nodes"
default y
depends on S390
depends on ZCRYPT
help
With this option enabled the zcrypt device driver can
provide multiple devices nodes in /dev. Each device
node can get customized to limit access and narrow
down the use of the available crypto hardware.
config PKEY
tristate "Kernel API for protected key handling"
depends on S390
......
......@@ -65,12 +65,11 @@ static struct device *ap_root_device;
DEFINE_SPINLOCK(ap_list_lock);
LIST_HEAD(ap_card_list);
/* Default permissions (card and domain masking) */
static struct ap_perms {
DECLARE_BITMAP(apm, AP_DEVICES);
DECLARE_BITMAP(aqm, AP_DOMAINS);
} ap_perms;
static DEFINE_MUTEX(ap_perms_mutex);
/* Default permissions (ioctl, card and domain masking) */
struct ap_perms ap_perms;
EXPORT_SYMBOL(ap_perms);
DEFINE_MUTEX(ap_perms_mutex);
EXPORT_SYMBOL(ap_perms_mutex);
static struct ap_config_info *ap_configuration;
static bool initialised;
......@@ -944,21 +943,9 @@ static int modify_bitmap(const char *str, unsigned long *bitmap, int bits)
return 0;
}
/*
* process_mask_arg() - parse a bitmap string and clear/set the
* bits in the bitmap accordingly. The string may be given as
* absolute value, a hex string like 0x1F2E3D4C5B6A" simple over-
* writing the current content of the bitmap. Or as relative string
* like "+1-16,-32,-0x40,+128" where only single bits or ranges of
* bits are cleared or set. Distinction is done based on the very
* first character which may be '+' or '-' for the relative string
* and othewise assume to be an absolute value string. If parsing fails
* a negative errno value is returned. All arguments and bitmaps are
* big endian order.
*/
static int process_mask_arg(const char *str,
unsigned long *bitmap, int bits,
struct mutex *lock)
int ap_parse_mask_str(const char *str,
unsigned long *bitmap, int bits,
struct mutex *lock)
{
unsigned long *newmap, size;
int rc;
......@@ -989,6 +976,7 @@ static int process_mask_arg(const char *str,
kfree(newmap);
return rc;
}
EXPORT_SYMBOL(ap_parse_mask_str);
/*
* AP bus attributes.
......@@ -1161,7 +1149,7 @@ static ssize_t apmask_store(struct bus_type *bus, const char *buf,
{
int rc;
rc = process_mask_arg(buf, ap_perms.apm, AP_DEVICES, &ap_perms_mutex);
rc = ap_parse_mask_str(buf, ap_perms.apm, AP_DEVICES, &ap_perms_mutex);
if (rc)
return rc;
......@@ -1192,7 +1180,7 @@ static ssize_t aqmask_store(struct bus_type *bus, const char *buf,
{
int rc;
rc = process_mask_arg(buf, ap_perms.aqm, AP_DOMAINS, &ap_perms_mutex);
rc = ap_parse_mask_str(buf, ap_perms.aqm, AP_DOMAINS, &ap_perms_mutex);
if (rc)
return rc;
......@@ -1490,21 +1478,22 @@ static int __init ap_debug_init(void)
static void __init ap_perms_init(void)
{
/* all resources useable if no kernel parameter string given */
memset(&ap_perms.ioctlm, 0xFF, sizeof(ap_perms.ioctlm));
memset(&ap_perms.apm, 0xFF, sizeof(ap_perms.apm));
memset(&ap_perms.aqm, 0xFF, sizeof(ap_perms.aqm));
/* apm kernel parameter string */
if (apm_str) {
memset(&ap_perms.apm, 0, sizeof(ap_perms.apm));
process_mask_arg(apm_str, ap_perms.apm, AP_DEVICES,
&ap_perms_mutex);
ap_parse_mask_str(apm_str, ap_perms.apm, AP_DEVICES,
&ap_perms_mutex);
}
/* aqm kernel parameter string */
if (aqm_str) {
memset(&ap_perms.aqm, 0, sizeof(ap_perms.aqm));
process_mask_arg(aqm_str, ap_perms.aqm, AP_DOMAINS,
&ap_perms_mutex);
ap_parse_mask_str(aqm_str, ap_perms.aqm, AP_DOMAINS,
&ap_perms_mutex);
}
}
......@@ -1527,7 +1516,7 @@ static int __init ap_module_init(void)
return -ENODEV;
}
/* set up the AP permissions (ap and aq masks) */
/* set up the AP permissions (ioctls, ap and aq masks) */
ap_perms_init();
/* Get AP configuration data if available */
......
......@@ -20,6 +20,7 @@
#define AP_DEVICES 256 /* Number of AP devices. */
#define AP_DOMAINS 256 /* Number of AP domains. */
#define AP_IOCTLS 256 /* Number of ioctls. */
#define AP_RESET_TIMEOUT (HZ*0.7) /* Time in ticks for reset timeouts. */
#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */
#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */
......@@ -257,6 +258,14 @@ void ap_queue_resume(struct ap_device *ap_dev);
struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
int comp_device_type, unsigned int functions);
struct ap_perms {
unsigned long ioctlm[BITS_TO_LONGS(AP_IOCTLS)];
unsigned long apm[BITS_TO_LONGS(AP_DEVICES)];
unsigned long aqm[BITS_TO_LONGS(AP_DOMAINS)];
};
extern struct ap_perms ap_perms;
extern struct mutex ap_perms_mutex;
/*
* check APQN for owned/reserved by ap bus and default driver(s).
* Checks if this APQN is or will be in use by the ap bus
......@@ -280,4 +289,20 @@ int ap_owned_by_def_drv(int card, int queue);
int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,
unsigned long *aqm);
/*
* ap_parse_mask_str() - helper function to parse a bitmap string
* and clear/set the bits in the bitmap accordingly. The string may be
* given as absolute value, a hex string like 0x1F2E3D4C5B6A" simple
* overwriting the current content of the bitmap. Or as relative string
* like "+1-16,-32,-0x40,+128" where only single bits or ranges of
* bits are cleared or set. Distinction is done based on the very
* first character which may be '+' or '-' for the relative string
* and othewise assume to be an absolute value string. If parsing fails
* a negative errno value is returned. All arguments and bitmaps are
* big endian order.
*/
int ap_parse_mask_str(const char *str,
unsigned long *bitmap, int bits,
struct mutex *lock);
#endif /* _AP_BUS_H_ */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment