diff options
author | Ingo Franzki <ifranzki@linux.ibm.com> | 2018-08-23 11:49:38 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2018-10-10 01:37:18 -0400 |
commit | cb26b9ff7187ea79698f5e872d713f30affcc0a3 (patch) | |
tree | 8efa20448fa9ac8480880510a35d75795cc9186e /drivers/s390/crypto/pkey_api.c | |
parent | af504452d10ece7c6d68bc9f90f478ebecd7ce76 (diff) |
s390/pkey: Introduce new API for random protected key verification
Introduce a new ioctl API and in-kernel API to verify if a
random protected key is still valid. A protected key is
invalid when its wrapping key verification pattern does not
match the verification pattern of the LPAR. Each time an LPAR
is activated, a new LPAR wrapping key is generated and the
wrapping key verification pattern is updated.
Both APIs are described in detail in the header files
arch/s390/include/asm/pkey.h and arch/s390/include/uapi/asm/pkey.h.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/crypto/pkey_api.c')
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index d0160a18081a..c592270b906a 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/zcrypt.h> | 20 | #include <asm/zcrypt.h> |
21 | #include <asm/cpacf.h> | 21 | #include <asm/cpacf.h> |
22 | #include <asm/pkey.h> | 22 | #include <asm/pkey.h> |
23 | #include <crypto/aes.h> | ||
23 | 24 | ||
24 | #include "zcrypt_api.h" | 25 | #include "zcrypt_api.h" |
25 | 26 | ||
@@ -1114,6 +1115,52 @@ int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey) | |||
1114 | EXPORT_SYMBOL(pkey_genprotkey); | 1115 | EXPORT_SYMBOL(pkey_genprotkey); |
1115 | 1116 | ||
1116 | /* | 1117 | /* |
1118 | * Verify if a protected key is still valid | ||
1119 | */ | ||
1120 | int pkey_verifyprotkey(const struct pkey_protkey *protkey) | ||
1121 | { | ||
1122 | unsigned long fc; | ||
1123 | struct { | ||
1124 | u8 iv[AES_BLOCK_SIZE]; | ||
1125 | u8 key[MAXPROTKEYSIZE]; | ||
1126 | } param; | ||
1127 | u8 null_msg[AES_BLOCK_SIZE]; | ||
1128 | u8 dest_buf[AES_BLOCK_SIZE]; | ||
1129 | unsigned int k; | ||
1130 | |||
1131 | switch (protkey->type) { | ||
1132 | case PKEY_KEYTYPE_AES_128: | ||
1133 | fc = CPACF_KMC_PAES_128; | ||
1134 | break; | ||
1135 | case PKEY_KEYTYPE_AES_192: | ||
1136 | fc = CPACF_KMC_PAES_192; | ||
1137 | break; | ||
1138 | case PKEY_KEYTYPE_AES_256: | ||
1139 | fc = CPACF_KMC_PAES_256; | ||
1140 | break; | ||
1141 | default: | ||
1142 | DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, | ||
1143 | protkey->type); | ||
1144 | return -EINVAL; | ||
1145 | } | ||
1146 | |||
1147 | memset(null_msg, 0, sizeof(null_msg)); | ||
1148 | |||
1149 | memset(param.iv, 0, sizeof(param.iv)); | ||
1150 | memcpy(param.key, protkey->protkey, sizeof(param.key)); | ||
1151 | |||
1152 | k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, | ||
1153 | sizeof(null_msg)); | ||
1154 | if (k != sizeof(null_msg)) { | ||
1155 | DEBUG_ERR("%s protected key is not valid\n", __func__); | ||
1156 | return -EKEYREJECTED; | ||
1157 | } | ||
1158 | |||
1159 | return 0; | ||
1160 | } | ||
1161 | EXPORT_SYMBOL(pkey_verifyprotkey); | ||
1162 | |||
1163 | /* | ||
1117 | * File io functions | 1164 | * File io functions |
1118 | */ | 1165 | */ |
1119 | 1166 | ||
@@ -1243,6 +1290,16 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, | |||
1243 | return -EFAULT; | 1290 | return -EFAULT; |
1244 | break; | 1291 | break; |
1245 | } | 1292 | } |
1293 | case PKEY_VERIFYPROTK: { | ||
1294 | struct pkey_verifyprotk __user *uvp = (void __user *) arg; | ||
1295 | struct pkey_verifyprotk kvp; | ||
1296 | |||
1297 | if (copy_from_user(&kvp, uvp, sizeof(kvp))) | ||
1298 | return -EFAULT; | ||
1299 | rc = pkey_verifyprotkey(&kvp.protkey); | ||
1300 | DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); | ||
1301 | break; | ||
1302 | } | ||
1246 | default: | 1303 | default: |
1247 | /* unknown/unsupported ioctl cmd */ | 1304 | /* unknown/unsupported ioctl cmd */ |
1248 | return -ENOTTY; | 1305 | return -ENOTTY; |
@@ -1504,7 +1561,7 @@ static struct miscdevice pkey_dev = { | |||
1504 | */ | 1561 | */ |
1505 | static int __init pkey_init(void) | 1562 | static int __init pkey_init(void) |
1506 | { | 1563 | { |
1507 | cpacf_mask_t pckmo_functions; | 1564 | cpacf_mask_t pckmo_functions, kmc_functions; |
1508 | 1565 | ||
1509 | /* check for pckmo instructions available */ | 1566 | /* check for pckmo instructions available */ |
1510 | if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) | 1567 | if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) |
@@ -1514,6 +1571,14 @@ static int __init pkey_init(void) | |||
1514 | !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY)) | 1571 | !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY)) |
1515 | return -EOPNOTSUPP; | 1572 | return -EOPNOTSUPP; |
1516 | 1573 | ||
1574 | /* check for kmc instructions available */ | ||
1575 | if (!cpacf_query(CPACF_KMC, &kmc_functions)) | ||
1576 | return -EOPNOTSUPP; | ||
1577 | if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || | ||
1578 | !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || | ||
1579 | !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) | ||
1580 | return -EOPNOTSUPP; | ||
1581 | |||
1517 | pkey_debug_init(); | 1582 | pkey_debug_init(); |
1518 | 1583 | ||
1519 | return misc_register(&pkey_dev); | 1584 | return misc_register(&pkey_dev); |