Skip to content

Commit fd19755

Browse files
hfreudehcahca
authored andcommitted
s390/pkey: Add AES xts and HMAC clear key token support
Add support for deriving protected keys from clear key token for AES xts and HMAC keys via PCKMO instruction. Add support for protected key generation and unwrap of protected key tokens for these key types. Furthermore 4 new sysfs attributes are introduced: - /sys/devices/virtual/misc/pkey/protkey/protkey_aes_xts_128 - /sys/devices/virtual/misc/pkey/protkey/protkey_aes_xts_256 - /sys/devices/virtual/misc/pkey/protkey/protkey_hmac_512 - /sys/devices/virtual/misc/pkey/protkey/protkey_hmac_1024 Signed-off-by: Harald Freudenberger <[email protected]> Reviewed-by: Ingo Franzki <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent 8fe3218 commit fd19755

File tree

4 files changed

+240
-13
lines changed

4 files changed

+240
-13
lines changed

arch/s390/include/uapi/asm/pkey.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
#define PKEY_KEYTYPE_ECC_P521 7
4242
#define PKEY_KEYTYPE_ECC_ED25519 8
4343
#define PKEY_KEYTYPE_ECC_ED448 9
44+
#define PKEY_KEYTYPE_AES_XTS_128 10
45+
#define PKEY_KEYTYPE_AES_XTS_256 11
46+
#define PKEY_KEYTYPE_HMAC_512 12
47+
#define PKEY_KEYTYPE_HMAC_1024 13
4448

4549
/* the newer ioctls use a pkey_key_type enum for type information */
4650
enum pkey_key_type {

drivers/s390/crypto/pkey_base.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,22 @@ extern debug_info_t *pkey_dbf_info;
3333
#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */
3434
#define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */
3535

36-
/* inside view of a protected key token (only type 0x00 version 0x01) */
36+
/* inside view of a generic protected key token */
37+
struct protkeytoken {
38+
u8 type; /* 0x00 for PAES specific key tokens */
39+
u8 res0[3];
40+
u8 version; /* should be 0x01 for protected key token */
41+
u8 res1[3];
42+
u32 keytype; /* key type, one of the PKEY_KEYTYPE values */
43+
u32 len; /* bytes actually stored in protkey[] */
44+
u8 protkey[]; /* the protected key blob */
45+
} __packed;
46+
47+
/* inside view of a protected AES key token */
3748
struct protaeskeytoken {
3849
u8 type; /* 0x00 for PAES specific key tokens */
3950
u8 res0[3];
40-
u8 version; /* should be 0x01 for protected AES key token */
51+
u8 version; /* should be 0x01 for protected key token */
4152
u8 res1[3];
4253
u32 keytype; /* key type, one of the PKEY_KEYTYPE values */
4354
u32 len; /* bytes actually stored in protkey[] */

drivers/s390/crypto/pkey_pckmo.c

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ static bool is_pckmo_key(const u8 *key, u32 keylen)
4747
case PKEY_KEYTYPE_ECC_P521:
4848
case PKEY_KEYTYPE_ECC_ED25519:
4949
case PKEY_KEYTYPE_ECC_ED448:
50+
case PKEY_KEYTYPE_AES_XTS_128:
51+
case PKEY_KEYTYPE_AES_XTS_256:
52+
case PKEY_KEYTYPE_HMAC_512:
53+
case PKEY_KEYTYPE_HMAC_1024:
5054
return true;
5155
default:
5256
return false;
@@ -81,7 +85,7 @@ static int pckmo_clr2protkey(u32 keytype, const u8 *clrkey, u32 clrkeylen,
8185
static cpacf_mask_t pckmo_functions;
8286

8387
int keysize, rc = -EINVAL;
84-
u8 paramblock[112];
88+
u8 paramblock[160];
8589
u32 pkeytype;
8690
long fc;
8791

@@ -134,6 +138,30 @@ static int pckmo_clr2protkey(u32 keytype, const u8 *clrkey, u32 clrkeylen,
134138
pkeytype = PKEY_KEYTYPE_ECC;
135139
fc = CPACF_PCKMO_ENC_ECC_ED448_KEY;
136140
break;
141+
case PKEY_KEYTYPE_AES_XTS_128:
142+
/* 2x16 byte keys, 32 byte aes wkvp, total 64 bytes */
143+
keysize = 32;
144+
pkeytype = PKEY_KEYTYPE_AES_XTS_128;
145+
fc = CPACF_PCKMO_ENC_AES_XTS_128_DOUBLE_KEY;
146+
break;
147+
case PKEY_KEYTYPE_AES_XTS_256:
148+
/* 2x32 byte keys, 32 byte aes wkvp, total 96 bytes */
149+
keysize = 64;
150+
pkeytype = PKEY_KEYTYPE_AES_XTS_256;
151+
fc = CPACF_PCKMO_ENC_AES_XTS_256_DOUBLE_KEY;
152+
break;
153+
case PKEY_KEYTYPE_HMAC_512:
154+
/* 64 byte key, 32 byte aes wkvp, total 96 bytes */
155+
keysize = 64;
156+
pkeytype = PKEY_KEYTYPE_HMAC_512;
157+
fc = CPACF_PCKMO_ENC_HMAC_512_KEY;
158+
break;
159+
case PKEY_KEYTYPE_HMAC_1024:
160+
/* 128 byte key, 32 byte aes wkvp, total 160 bytes */
161+
keysize = 128;
162+
pkeytype = PKEY_KEYTYPE_HMAC_1024;
163+
fc = CPACF_PCKMO_ENC_HMAC_1024_KEY;
164+
break;
137165
default:
138166
PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n",
139167
__func__, keytype);
@@ -260,14 +288,39 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
260288

261289
switch (hdr->version) {
262290
case TOKVER_PROTECTED_KEY: {
263-
struct protaeskeytoken *t;
291+
struct protkeytoken *t = (struct protkeytoken *)key;
264292

265-
if (keylen != sizeof(struct protaeskeytoken))
293+
if (keylen < sizeof(*t))
266294
goto out;
267-
t = (struct protaeskeytoken *)key;
268-
rc = pckmo_verify_protkey(t->protkey, t->len, t->keytype);
269-
if (rc)
295+
switch (t->keytype) {
296+
case PKEY_KEYTYPE_AES_128:
297+
case PKEY_KEYTYPE_AES_192:
298+
case PKEY_KEYTYPE_AES_256:
299+
if (keylen != sizeof(struct protaeskeytoken))
300+
goto out;
301+
rc = pckmo_verify_protkey(t->protkey, t->len,
302+
t->keytype);
303+
if (rc)
304+
goto out;
305+
break;
306+
case PKEY_KEYTYPE_AES_XTS_128:
307+
if (t->len != 64 || keylen != sizeof(*t) + t->len)
308+
goto out;
309+
break;
310+
case PKEY_KEYTYPE_AES_XTS_256:
311+
case PKEY_KEYTYPE_HMAC_512:
312+
if (t->len != 96 || keylen != sizeof(*t) + t->len)
313+
goto out;
314+
break;
315+
case PKEY_KEYTYPE_HMAC_1024:
316+
if (t->len != 160 || keylen != sizeof(*t) + t->len)
317+
goto out;
318+
break;
319+
default:
320+
PKEY_DBF_ERR("%s protected key token: unknown keytype %u\n",
321+
__func__, t->keytype);
270322
goto out;
323+
}
271324
memcpy(protkey, t->protkey, t->len);
272325
*protkeylen = t->len;
273326
*protkeytype = t->keytype;
@@ -301,6 +354,18 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
301354
case PKEY_KEYTYPE_ECC_ED448:
302355
keysize = 64;
303356
break;
357+
case PKEY_KEYTYPE_AES_XTS_128:
358+
keysize = 32;
359+
break;
360+
case PKEY_KEYTYPE_AES_XTS_256:
361+
keysize = 64;
362+
break;
363+
case PKEY_KEYTYPE_HMAC_512:
364+
keysize = 64;
365+
break;
366+
case PKEY_KEYTYPE_HMAC_1024:
367+
keysize = 128;
368+
break;
304369
default:
305370
break;
306371
}
@@ -337,14 +402,29 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
337402
static int pckmo_gen_protkey(u32 keytype, u32 subtype,
338403
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
339404
{
340-
u8 clrkey[32];
405+
u8 clrkey[128];
341406
int keysize;
342407
int rc;
343408

344-
keysize = pkey_keytype_aes_to_size(keytype);
345-
if (!keysize) {
346-
PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", __func__,
347-
keytype);
409+
switch (keytype) {
410+
case PKEY_KEYTYPE_AES_128:
411+
case PKEY_KEYTYPE_AES_192:
412+
case PKEY_KEYTYPE_AES_256:
413+
keysize = pkey_keytype_aes_to_size(keytype);
414+
break;
415+
case PKEY_KEYTYPE_AES_XTS_128:
416+
keysize = 32;
417+
break;
418+
case PKEY_KEYTYPE_AES_XTS_256:
419+
case PKEY_KEYTYPE_HMAC_512:
420+
keysize = 64;
421+
break;
422+
case PKEY_KEYTYPE_HMAC_1024:
423+
keysize = 128;
424+
break;
425+
default:
426+
PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
427+
__func__, keytype);
348428
return -EINVAL;
349429
}
350430
if (subtype != PKEY_TYPE_PROTKEY) {

drivers/s390/crypto/pkey_sysfs.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,90 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf,
9999
return sizeof(protkeytoken);
100100
}
101101

102+
/*
103+
* Sysfs attribute read function for the AES XTS prot key binary attributes.
104+
* The implementation can not deal with partial reads, because a new random
105+
* protected key blob is generated with each read. In case of partial reads
106+
* (i.e. off != 0 or count < key blob size) -EINVAL is returned.
107+
*/
108+
static ssize_t pkey_protkey_aes_xts_attr_read(u32 keytype, char *buf,
109+
loff_t off, size_t count)
110+
{
111+
struct protkeytoken *t = (struct protkeytoken *)buf;
112+
u32 protlen, prottype;
113+
int rc;
114+
115+
switch (keytype) {
116+
case PKEY_KEYTYPE_AES_XTS_128:
117+
protlen = 64;
118+
break;
119+
case PKEY_KEYTYPE_AES_XTS_256:
120+
protlen = 96;
121+
break;
122+
default:
123+
return -EINVAL;
124+
}
125+
126+
if (off != 0 || count < sizeof(*t) + protlen)
127+
return -EINVAL;
128+
129+
memset(t, 0, sizeof(*t) + protlen);
130+
t->type = TOKTYPE_NON_CCA;
131+
t->version = TOKVER_PROTECTED_KEY;
132+
t->keytype = keytype;
133+
134+
rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_PROTKEY, 0, 0,
135+
t->protkey, &protlen, &prottype);
136+
if (rc)
137+
return rc;
138+
139+
t->len = protlen;
140+
141+
return sizeof(*t) + protlen;
142+
}
143+
144+
/*
145+
* Sysfs attribute read function for the HMAC prot key binary attributes.
146+
* The implementation can not deal with partial reads, because a new random
147+
* protected key blob is generated with each read. In case of partial reads
148+
* (i.e. off != 0 or count < key blob size) -EINVAL is returned.
149+
*/
150+
static ssize_t pkey_protkey_hmac_attr_read(u32 keytype, char *buf,
151+
loff_t off, size_t count)
152+
{
153+
struct protkeytoken *t = (struct protkeytoken *)buf;
154+
u32 protlen, prottype;
155+
int rc;
156+
157+
switch (keytype) {
158+
case PKEY_KEYTYPE_HMAC_512:
159+
protlen = 96;
160+
break;
161+
case PKEY_KEYTYPE_HMAC_1024:
162+
protlen = 160;
163+
break;
164+
default:
165+
return -EINVAL;
166+
}
167+
168+
if (off != 0 || count < sizeof(*t) + protlen)
169+
return -EINVAL;
170+
171+
memset(t, 0, sizeof(*t) + protlen);
172+
t->type = TOKTYPE_NON_CCA;
173+
t->version = TOKVER_PROTECTED_KEY;
174+
t->keytype = keytype;
175+
176+
rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_PROTKEY, 0, 0,
177+
t->protkey, &protlen, &prottype);
178+
if (rc)
179+
return rc;
180+
181+
t->len = protlen;
182+
183+
return sizeof(*t) + protlen;
184+
}
185+
102186
static ssize_t protkey_aes_128_read(struct file *filp,
103187
struct kobject *kobj,
104188
struct bin_attribute *attr,
@@ -149,18 +233,66 @@ static ssize_t protkey_aes_256_xts_read(struct file *filp,
149233
off, count);
150234
}
151235

236+
static ssize_t protkey_aes_xts_128_read(struct file *filp,
237+
struct kobject *kobj,
238+
struct bin_attribute *attr,
239+
char *buf, loff_t off,
240+
size_t count)
241+
{
242+
return pkey_protkey_aes_xts_attr_read(PKEY_KEYTYPE_AES_XTS_128,
243+
buf, off, count);
244+
}
245+
246+
static ssize_t protkey_aes_xts_256_read(struct file *filp,
247+
struct kobject *kobj,
248+
struct bin_attribute *attr,
249+
char *buf, loff_t off,
250+
size_t count)
251+
{
252+
return pkey_protkey_aes_xts_attr_read(PKEY_KEYTYPE_AES_XTS_256,
253+
buf, off, count);
254+
}
255+
256+
static ssize_t protkey_hmac_512_read(struct file *filp,
257+
struct kobject *kobj,
258+
struct bin_attribute *attr,
259+
char *buf, loff_t off,
260+
size_t count)
261+
{
262+
return pkey_protkey_hmac_attr_read(PKEY_KEYTYPE_HMAC_512,
263+
buf, off, count);
264+
}
265+
266+
static ssize_t protkey_hmac_1024_read(struct file *filp,
267+
struct kobject *kobj,
268+
struct bin_attribute *attr,
269+
char *buf, loff_t off,
270+
size_t count)
271+
{
272+
return pkey_protkey_hmac_attr_read(PKEY_KEYTYPE_HMAC_1024,
273+
buf, off, count);
274+
}
275+
152276
static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken));
153277
static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken));
154278
static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken));
155279
static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken));
156280
static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken));
281+
static BIN_ATTR_RO(protkey_aes_xts_128, sizeof(struct protkeytoken) + 64);
282+
static BIN_ATTR_RO(protkey_aes_xts_256, sizeof(struct protkeytoken) + 96);
283+
static BIN_ATTR_RO(protkey_hmac_512, sizeof(struct protkeytoken) + 96);
284+
static BIN_ATTR_RO(protkey_hmac_1024, sizeof(struct protkeytoken) + 160);
157285

158286
static struct bin_attribute *protkey_attrs[] = {
159287
&bin_attr_protkey_aes_128,
160288
&bin_attr_protkey_aes_192,
161289
&bin_attr_protkey_aes_256,
162290
&bin_attr_protkey_aes_128_xts,
163291
&bin_attr_protkey_aes_256_xts,
292+
&bin_attr_protkey_aes_xts_128,
293+
&bin_attr_protkey_aes_xts_256,
294+
&bin_attr_protkey_hmac_512,
295+
&bin_attr_protkey_hmac_1024,
164296
NULL
165297
};
166298

0 commit comments

Comments
 (0)