Skip to content

Commit d1fdfb0

Browse files
holger-denglerhcahca
authored andcommitted
s390/pkey: fix PKEY_TYPE_EP11_AES handling in PKEY_KBLOB2PROTK[23]
Commit 'fa6999e326fe ("s390/pkey: support CCA and EP11 secure ECC private keys")' introduced a new PKEY_TYPE_EP11_AES type for the PKEY_KBLOB2PROTK2 and a new IOCTL, PKEY_KBLOB2PROTK3, which both allows userspace to convert opaque securekey blobs of this type into protectedkey blobs. Unfortunately, all PKEY_KBLOB2PROTK2 and PKEY_KBLOB2PROTK3 IOCTL requests with this keyblobs of this type return with an error (-EINVAL). Fix PKEY_TYPE_EP11_AES handling in PKEY_KBLOB2PROTK2 and PKEY_KBLOB2PROTK3 IOCTLs, so that userspace can convert PKEY_TYPE_EP11_AES keyblobs into protectedkey blobs. Add a helper function to decode the start and size of the internal header as well as start and size of the keyblob payload of an existing keyblob. Also validate the length of header and keyblob, as well as the keyblob magic. Introduce another helper function, which handles a raw key wrapping request and do the keyblob decoding in the calling function. Remove all other header-related calculations. Fixes: fa6999e ("s390/pkey: support CCA and EP11 secure ECC private keys") Signed-off-by: Holger Dengler <[email protected]> Reviewed-by: Ingo Franzki <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent da2863f commit d1fdfb0

File tree

3 files changed

+100
-62
lines changed

3 files changed

+100
-62
lines changed

drivers/s390/crypto/pkey_api.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,9 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
288288
/*
289289
* Find card and transform EP11 secure key into protected key.
290290
*/
291-
static int pkey_ep11key2pkey(const u8 *key, u8 *protkey,
292-
u32 *protkeylen, u32 *protkeytype)
291+
static int pkey_ep11key2pkey(const u8 *key, size_t keylen,
292+
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
293293
{
294-
struct ep11keyblob *kb = (struct ep11keyblob *)key;
295294
u32 nr_apqns, *apqns = NULL;
296295
u16 card, dom;
297296
int i, rc;
@@ -300,15 +299,16 @@ static int pkey_ep11key2pkey(const u8 *key, u8 *protkey,
300299

301300
/* build a list of apqns suitable for this key */
302301
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
303-
ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
302+
ZCRYPT_CEX7, EP11_API_V,
303+
ep11_kb_wkvp(key, keylen));
304304
if (rc)
305305
goto out;
306306

307307
/* go through the list of apqns and try to derive an pkey */
308308
for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
309309
card = apqns[i] >> 16;
310310
dom = apqns[i] & 0xFFFF;
311-
rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
311+
rc = ep11_kblob2protkey(card, dom, key, keylen,
312312
protkey, protkeylen, protkeytype);
313313
if (rc == 0)
314314
break;
@@ -496,7 +496,7 @@ static int nonccatokaes2pkey(const struct clearkeytoken *t,
496496
tmpbuf, &tmpbuflen);
497497
if (rc)
498498
goto failure;
499-
rc = pkey_ep11key2pkey(tmpbuf,
499+
rc = pkey_ep11key2pkey(tmpbuf, tmpbuflen,
500500
protkey, protkeylen, protkeytype);
501501
if (!rc)
502502
goto out;
@@ -612,7 +612,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
612612
rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
613613
if (rc)
614614
goto out;
615-
rc = pkey_ep11key2pkey(key,
615+
rc = pkey_ep11key2pkey(key, keylen,
616616
protkey, protkeylen, protkeytype);
617617
break;
618618
}
@@ -621,7 +621,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
621621
rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1);
622622
if (rc)
623623
goto out;
624-
rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header),
624+
rc = pkey_ep11key2pkey(key, keylen,
625625
protkey, protkeylen, protkeytype);
626626
break;
627627
default:
@@ -963,10 +963,12 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
963963
}
964964
} else if (hdr->type == TOKTYPE_NON_CCA) {
965965
if (hdr->version == TOKVER_EP11_AES) {
966-
if (keylen < sizeof(struct ep11keyblob))
967-
return -EINVAL;
968966
if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
969967
return -EINVAL;
968+
} else if (hdr->version == TOKVER_EP11_AES_WITH_HEADER) {
969+
if (ep11_check_aes_key_with_hdr(debug_info, 3,
970+
key, keylen, 1))
971+
return -EINVAL;
970972
} else {
971973
return pkey_nonccatok2pkey(key, keylen,
972974
protkey, protkeylen,
@@ -994,10 +996,7 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
994996
protkey, protkeylen,
995997
protkeytype);
996998
} else {
997-
/* EP11 AES secure key blob */
998-
struct ep11keyblob *kb = (struct ep11keyblob *)key;
999-
1000-
rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
999+
rc = ep11_kblob2protkey(card, dom, key, keylen,
10011000
protkey, protkeylen,
10021001
protkeytype);
10031002
}
@@ -1257,12 +1256,14 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns,
12571256
hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
12581257
is_ep11_keyblob(key + sizeof(struct ep11kblob_header)))
12591258
rc = ep11_kblob2protkey(card, dom, key, hdr->len,
1260-
protkey, protkeylen, protkeytype);
1259+
protkey, protkeylen,
1260+
protkeytype);
12611261
else if (hdr->type == TOKTYPE_NON_CCA &&
12621262
hdr->version == TOKVER_EP11_AES &&
12631263
is_ep11_keyblob(key))
12641264
rc = ep11_kblob2protkey(card, dom, key, hdr->len,
1265-
protkey, protkeylen, protkeytype);
1265+
protkey, protkeylen,
1266+
protkeytype);
12661267
else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
12671268
hdr->version == TOKVER_CCA_AES)
12681269
rc = cca_sec2protkey(card, dom, key, protkey,

drivers/s390/crypto/zcrypt_ep11misc.c

Lines changed: 77 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,65 @@ static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver,
157157
return rc;
158158
}
159159

160+
static int ep11_kb_decode(const u8 *kb, size_t kblen,
161+
struct ep11kblob_header **kbhdr, size_t *kbhdrsize,
162+
struct ep11keyblob **kbpl, size_t *kbplsize)
163+
{
164+
struct ep11kblob_header *tmph, *hdr = NULL;
165+
size_t hdrsize = 0, plsize = 0;
166+
struct ep11keyblob *pl = NULL;
167+
int rc = -EINVAL;
168+
u8 *tmpp;
169+
170+
if (kblen < sizeof(struct ep11kblob_header))
171+
goto out;
172+
tmph = (struct ep11kblob_header *)kb;
173+
174+
if (tmph->type != TOKTYPE_NON_CCA &&
175+
tmph->len > kblen)
176+
goto out;
177+
178+
if (ep11_kb_split(kb, kblen, tmph->version,
179+
&hdr, &hdrsize, &tmpp, &plsize))
180+
goto out;
181+
182+
if (plsize < sizeof(struct ep11keyblob))
183+
goto out;
184+
185+
if (!is_ep11_keyblob(tmpp))
186+
goto out;
187+
188+
pl = (struct ep11keyblob *)tmpp;
189+
plsize = hdr->len - hdrsize;
190+
191+
if (kbhdr)
192+
*kbhdr = hdr;
193+
if (kbhdrsize)
194+
*kbhdrsize = hdrsize;
195+
if (kbpl)
196+
*kbpl = pl;
197+
if (kbplsize)
198+
*kbplsize = plsize;
199+
200+
rc = 0;
201+
out:
202+
return rc;
203+
}
204+
205+
/*
206+
* For valid ep11 keyblobs, returns a reference to the wrappingkey verification
207+
* pattern. Otherwise NULL.
208+
*/
209+
const u8 *ep11_kb_wkvp(const u8 *keyblob, size_t keybloblen)
210+
{
211+
struct ep11keyblob *kb;
212+
213+
if (ep11_kb_decode(keyblob, keybloblen, NULL, NULL, &kb, NULL))
214+
return NULL;
215+
return kb->wkvp;
216+
}
217+
EXPORT_SYMBOL(ep11_kb_wkvp);
218+
160219
/*
161220
* Simple check if the key blob is a valid EP11 AES key blob with header.
162221
*/
@@ -1170,10 +1229,10 @@ static int ep11_unwrapkey(u16 card, u16 domain,
11701229
return 0;
11711230
}
11721231

1173-
static int ep11_wrapkey(u16 card, u16 domain,
1174-
const u8 *key, size_t keysize,
1175-
u32 mech, const u8 *iv,
1176-
u8 *databuf, size_t *datasize)
1232+
static int _ep11_wrapkey(u16 card, u16 domain,
1233+
const u8 *key, size_t keysize,
1234+
u32 mech, const u8 *iv,
1235+
u8 *databuf, size_t *datasize)
11771236
{
11781237
struct wk_req_pl {
11791238
struct pl_head head;
@@ -1203,20 +1262,10 @@ static int ep11_wrapkey(u16 card, u16 domain,
12031262
struct ep11_cprb *req = NULL, *rep = NULL;
12041263
struct ep11_target_dev target;
12051264
struct ep11_urb *urb = NULL;
1206-
struct ep11keyblob *kb;
12071265
size_t req_pl_size;
12081266
int api, rc = -ENOMEM;
1209-
bool has_header = false;
12101267
u8 *p;
12111268

1212-
/* maybe the session field holds a header with key info */
1213-
kb = (struct ep11keyblob *)key;
1214-
if (kb->head.type == TOKTYPE_NON_CCA &&
1215-
kb->head.version == TOKVER_EP11_AES) {
1216-
has_header = true;
1217-
keysize = min_t(size_t, kb->head.len, keysize);
1218-
}
1219-
12201269
/* request cprb and payload */
12211270
req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
12221271
+ ASN1TAGLEN(keysize) + 4;
@@ -1241,11 +1290,6 @@ static int ep11_wrapkey(u16 card, u16 domain,
12411290
}
12421291
/* key blob */
12431292
p += asn1tag_write(p, 0x04, key, keysize);
1244-
/* maybe the key argument needs the head data cleaned out */
1245-
if (has_header) {
1246-
kb = (struct ep11keyblob *)(p - keysize);
1247-
memset(&kb->head, 0, sizeof(kb->head));
1248-
}
12491293
/* empty kek tag */
12501294
*p++ = 0x04;
12511295
*p++ = 0;
@@ -1366,11 +1410,12 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
13661410
}
13671411
EXPORT_SYMBOL(ep11_clr2keyblob);
13681412

1369-
int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen,
1413+
int ep11_kblob2protkey(u16 card, u16 dom,
1414+
const u8 *keyblob, size_t keybloblen,
13701415
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
13711416
{
1372-
int rc = -EIO;
1373-
u8 *wkbuf = NULL;
1417+
struct ep11kblob_header *hdr;
1418+
struct ep11keyblob *key;
13741419
size_t wkbuflen, keylen;
13751420
struct wk_info {
13761421
u16 version;
@@ -1381,31 +1426,17 @@ int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen,
13811426
u8 res2[8];
13821427
u8 pkey[];
13831428
} __packed * wki;
1384-
const u8 *key;
1385-
struct ep11kblob_header *hdr;
1429+
u8 *wkbuf = NULL;
1430+
int rc = -EIO;
13861431

1387-
/* key with or without header ? */
1388-
hdr = (struct ep11kblob_header *)keyblob;
1389-
if (hdr->type == TOKTYPE_NON_CCA &&
1390-
(hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
1391-
hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
1392-
is_ep11_keyblob(keyblob + sizeof(struct ep11kblob_header))) {
1393-
/* EP11 AES or ECC key with header */
1394-
key = keyblob + sizeof(struct ep11kblob_header);
1395-
keylen = hdr->len - sizeof(struct ep11kblob_header);
1396-
} else if (hdr->type == TOKTYPE_NON_CCA &&
1397-
hdr->version == TOKVER_EP11_AES &&
1398-
is_ep11_keyblob(keyblob)) {
1399-
/* EP11 AES key (old style) */
1400-
key = keyblob;
1401-
keylen = hdr->len;
1402-
} else if (is_ep11_keyblob(keyblob)) {
1403-
/* raw EP11 key blob */
1404-
key = keyblob;
1405-
keylen = keybloblen;
1406-
} else {
1432+
if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen))
14071433
return -EINVAL;
1434+
1435+
if (hdr->version == TOKVER_EP11_AES) {
1436+
/* wipe overlayed header */
1437+
memset(hdr, 0, sizeof(*hdr));
14081438
}
1439+
/* !!! hdr is no longer a valid header !!! */
14091440

14101441
/* alloc temp working buffer */
14111442
wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
@@ -1414,8 +1445,8 @@ int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen,
14141445
return -ENOMEM;
14151446

14161447
/* ep11 secure key -> protected key + info */
1417-
rc = ep11_wrapkey(card, dom, key, keylen,
1418-
0, def_iv, wkbuf, &wkbuflen);
1448+
rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen,
1449+
0, def_iv, wkbuf, &wkbuflen);
14191450
if (rc) {
14201451
DEBUG_ERR(
14211452
"%s rewrapping ep11 key to pkey failed, rc=%d\n",

drivers/s390/crypto/zcrypt_ep11misc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ static inline bool is_ep11_keyblob(const u8 *key)
4848
return (kb->version == EP11_STRUCT_MAGIC);
4949
}
5050

51+
/*
52+
* For valid ep11 keyblobs, returns a reference to the wrappingkey verification
53+
* pattern. Otherwise NULL.
54+
*/
55+
const u8 *ep11_kb_wkvp(const u8 *kblob, size_t kbloblen);
56+
5157
/*
5258
* Simple check if the key blob is a valid EP11 AES key blob with header.
5359
* If checkcpacfexport is enabled, the key is also checked for the

0 commit comments

Comments
 (0)