Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/pkey: add support for ecc clear key

Add support for a new 'non CCA clear key token' with these
ECC clear keys supported:

- ECC P256
- ECC P384
- ECC P521
- ECC ED25519
- ECC ED448

This makes it possible to derive a protected key from this
ECC clear key input via PKEY_KBLOB2PROTK3 ioctl. As of now
the only way to derive protected keys from these clear key
tokens is via PCKMO instruction. For AES keys an alternate
path via creating a secure key from the clear key and then
derive a protected key from the secure key exists. This
alternate path is not implemented for ECC keys as it would
require to rearrange and maybe recalculate the clear key
material for input to derive an CCA or EP11 ECC secure key.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>

authored by

Harald Freudenberger and committed by
Alexander Gordeev
9e436c19 f370f45c

+208 -74
+6 -1
arch/s390/include/asm/cpacf.h
··· 2 2 /* 3 3 * CP Assist for Cryptographic Functions (CPACF) 4 4 * 5 - * Copyright IBM Corp. 2003, 2017 5 + * Copyright IBM Corp. 2003, 2023 6 6 * Author(s): Thomas Spatzier 7 7 * Jan Glauber 8 8 * Harald Freudenberger (freude@de.ibm.com) ··· 132 132 #define CPACF_PCKMO_ENC_AES_128_KEY 0x12 133 133 #define CPACF_PCKMO_ENC_AES_192_KEY 0x13 134 134 #define CPACF_PCKMO_ENC_AES_256_KEY 0x14 135 + #define CPACF_PCKMO_ENC_ECC_P256_KEY 0x20 136 + #define CPACF_PCKMO_ENC_ECC_P384_KEY 0x21 137 + #define CPACF_PCKMO_ENC_ECC_P521_KEY 0x22 138 + #define CPACF_PCKMO_ENC_ECC_ED25519_KEY 0x28 139 + #define CPACF_PCKMO_ENC_ECC_ED448_KEY 0x29 135 140 136 141 /* 137 142 * Function codes for the PRNO (PERFORM RANDOM NUMBER OPERATION)
+10 -5
arch/s390/include/uapi/asm/pkey.h
··· 2 2 /* 3 3 * Userspace interface to the pkey device driver 4 4 * 5 - * Copyright IBM Corp. 2017, 2019 5 + * Copyright IBM Corp. 2017, 2023 6 6 * 7 7 * Author: Harald Freudenberger <freude@de.ibm.com> 8 8 * ··· 32 32 #define MINKEYBLOBSIZE SECKEYBLOBSIZE 33 33 34 34 /* defines for the type field within the pkey_protkey struct */ 35 - #define PKEY_KEYTYPE_AES_128 1 36 - #define PKEY_KEYTYPE_AES_192 2 37 - #define PKEY_KEYTYPE_AES_256 3 38 - #define PKEY_KEYTYPE_ECC 4 35 + #define PKEY_KEYTYPE_AES_128 1 36 + #define PKEY_KEYTYPE_AES_192 2 37 + #define PKEY_KEYTYPE_AES_256 3 38 + #define PKEY_KEYTYPE_ECC 4 39 + #define PKEY_KEYTYPE_ECC_P256 5 40 + #define PKEY_KEYTYPE_ECC_P384 6 41 + #define PKEY_KEYTYPE_ECC_P521 7 42 + #define PKEY_KEYTYPE_ECC_ED25519 8 43 + #define PKEY_KEYTYPE_ECC_ED448 9 39 44 40 45 /* the newer ioctls use a pkey_key_type enum for type information */ 41 46 enum pkey_key_type {
+192 -68
drivers/s390/crypto/pkey_api.c
··· 2 2 /* 3 3 * pkey device driver 4 4 * 5 - * Copyright IBM Corp. 2017,2019 5 + * Copyright IBM Corp. 2017, 2023 6 + * 6 7 * Author(s): Harald Freudenberger 7 8 */ 8 9 ··· 33 32 MODULE_DESCRIPTION("s390 protected key interface"); 34 33 35 34 #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 35 + #define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header)) 36 36 #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ 37 37 #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 38 38 #define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */ ··· 74 72 } __packed; 75 73 76 74 /* inside view of a clear key token (type 0x00 version 0x02) */ 77 - struct clearaeskeytoken { 78 - u8 type; /* 0x00 for PAES specific key tokens */ 75 + struct clearkeytoken { 76 + u8 type; /* 0x00 for PAES specific key tokens */ 79 77 u8 res0[3]; 80 - u8 version; /* 0x02 for clear AES key token */ 78 + u8 version; /* 0x02 for clear key token */ 81 79 u8 res1[3]; 82 - u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 83 - u32 len; /* bytes actually stored in clearkey[] */ 80 + u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */ 81 + u32 len; /* bytes actually stored in clearkey[] */ 84 82 u8 clearkey[]; /* clear key value */ 85 83 } __packed; 84 + 85 + /* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */ 86 + static inline u32 pkey_keytype_aes_to_size(u32 keytype) 87 + { 88 + switch (keytype) { 89 + case PKEY_KEYTYPE_AES_128: 90 + return 16; 91 + case PKEY_KEYTYPE_AES_192: 92 + return 24; 93 + case PKEY_KEYTYPE_AES_256: 94 + return 32; 95 + default: 96 + return 0; 97 + } 98 + } 86 99 87 100 /* 88 101 * Create a protected key from a clear key value via PCKMO instruction. ··· 108 91 /* mask of available pckmo subfunctions */ 109 92 static cpacf_mask_t pckmo_functions; 110 93 111 - u8 paramblock[64]; 94 + u8 paramblock[112]; 95 + u32 pkeytype; 112 96 int keysize; 113 97 long fc; 114 98 115 99 switch (keytype) { 116 100 case PKEY_KEYTYPE_AES_128: 101 + /* 16 byte key, 32 byte aes wkvp, total 48 bytes */ 117 102 keysize = 16; 103 + pkeytype = keytype; 118 104 fc = CPACF_PCKMO_ENC_AES_128_KEY; 119 105 break; 120 106 case PKEY_KEYTYPE_AES_192: 107 + /* 24 byte key, 32 byte aes wkvp, total 56 bytes */ 121 108 keysize = 24; 109 + pkeytype = keytype; 122 110 fc = CPACF_PCKMO_ENC_AES_192_KEY; 123 111 break; 124 112 case PKEY_KEYTYPE_AES_256: 113 + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 125 114 keysize = 32; 115 + pkeytype = keytype; 126 116 fc = CPACF_PCKMO_ENC_AES_256_KEY; 117 + break; 118 + case PKEY_KEYTYPE_ECC_P256: 119 + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 120 + keysize = 32; 121 + pkeytype = PKEY_KEYTYPE_ECC; 122 + fc = CPACF_PCKMO_ENC_ECC_P256_KEY; 123 + break; 124 + case PKEY_KEYTYPE_ECC_P384: 125 + /* 48 byte key, 32 byte aes wkvp, total 80 bytes */ 126 + keysize = 48; 127 + pkeytype = PKEY_KEYTYPE_ECC; 128 + fc = CPACF_PCKMO_ENC_ECC_P384_KEY; 129 + break; 130 + case PKEY_KEYTYPE_ECC_P521: 131 + /* 80 byte key, 32 byte aes wkvp, total 112 bytes */ 132 + keysize = 80; 133 + pkeytype = PKEY_KEYTYPE_ECC; 134 + fc = CPACF_PCKMO_ENC_ECC_P521_KEY; 135 + break; 136 + case PKEY_KEYTYPE_ECC_ED25519: 137 + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 138 + keysize = 32; 139 + pkeytype = PKEY_KEYTYPE_ECC; 140 + fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY; 141 + break; 142 + case PKEY_KEYTYPE_ECC_ED448: 143 + /* 64 byte key, 32 byte aes wkvp, total 96 bytes */ 144 + keysize = 64; 145 + pkeytype = PKEY_KEYTYPE_ECC; 146 + fc = CPACF_PCKMO_ENC_ECC_ED448_KEY; 127 147 break; 128 148 default: 129 149 DEBUG_ERR("%s unknown/unsupported keytype %u\n", ··· 196 142 /* copy created protected key to key buffer including the wkvp block */ 197 143 *protkeylen = keysize + AES_WK_VP_SIZE; 198 144 memcpy(protkey, paramblock, *protkeylen); 199 - *protkeytype = keytype; 145 + *protkeytype = pkeytype; 200 146 201 147 return 0; 202 148 } ··· 373 319 int keysize; 374 320 int rc; 375 321 376 - switch (keytype) { 377 - case PKEY_KEYTYPE_AES_128: 378 - keysize = 16; 379 - break; 380 - case PKEY_KEYTYPE_AES_192: 381 - keysize = 24; 382 - break; 383 - case PKEY_KEYTYPE_AES_256: 384 - keysize = 32; 385 - break; 386 - default: 322 + keysize = pkey_keytype_aes_to_size(keytype); 323 + if (!keysize) { 387 324 DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 388 325 keytype); 389 326 return -EINVAL; ··· 449 404 return 0; 450 405 } 451 406 407 + /* Helper for pkey_nonccatok2pkey, handles aes clear key token */ 408 + static int nonccatokaes2pkey(const struct clearkeytoken *t, 409 + u8 *protkey, u32 *protkeylen, u32 *protkeytype) 410 + { 411 + size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); 412 + u8 *tmpbuf = NULL; 413 + u32 keysize; 414 + int rc; 415 + 416 + keysize = pkey_keytype_aes_to_size(t->keytype); 417 + if (!keysize) { 418 + DEBUG_ERR("%s unknown/unsupported keytype %u\n", 419 + __func__, t->keytype); 420 + return -EINVAL; 421 + } 422 + if (t->len != keysize) { 423 + DEBUG_ERR("%s non clear key aes token: invalid key len %u\n", 424 + __func__, t->len); 425 + return -EINVAL; 426 + } 427 + 428 + /* try direct way with the PCKMO instruction */ 429 + rc = pkey_clr2protkey(t->keytype, t->clearkey, 430 + protkey, protkeylen, protkeytype); 431 + if (!rc) 432 + goto out; 433 + 434 + /* PCKMO failed, so try the CCA secure key way */ 435 + tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 436 + if (!tmpbuf) 437 + return -ENOMEM; 438 + zcrypt_wait_api_operational(); 439 + rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); 440 + if (rc) 441 + goto try_via_ep11; 442 + rc = pkey_skey2pkey(tmpbuf, 443 + protkey, protkeylen, protkeytype); 444 + if (!rc) 445 + goto out; 446 + 447 + try_via_ep11: 448 + /* if the CCA way also failed, let's try via EP11 */ 449 + rc = pkey_clr2ep11key(t->clearkey, t->len, 450 + tmpbuf, &tmpbuflen); 451 + if (rc) 452 + goto failure; 453 + rc = pkey_ep11key2pkey(tmpbuf, 454 + protkey, protkeylen, protkeytype); 455 + if (!rc) 456 + goto out; 457 + 458 + failure: 459 + DEBUG_ERR("%s unable to build protected key from clear", __func__); 460 + 461 + out: 462 + kfree(tmpbuf); 463 + return rc; 464 + } 465 + 466 + /* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ 467 + static int nonccatokecc2pkey(const struct clearkeytoken *t, 468 + u8 *protkey, u32 *protkeylen, u32 *protkeytype) 469 + { 470 + u32 keylen; 471 + int rc; 472 + 473 + switch (t->keytype) { 474 + case PKEY_KEYTYPE_ECC_P256: 475 + keylen = 32; 476 + break; 477 + case PKEY_KEYTYPE_ECC_P384: 478 + keylen = 48; 479 + break; 480 + case PKEY_KEYTYPE_ECC_P521: 481 + keylen = 80; 482 + break; 483 + case PKEY_KEYTYPE_ECC_ED25519: 484 + keylen = 32; 485 + break; 486 + case PKEY_KEYTYPE_ECC_ED448: 487 + keylen = 64; 488 + break; 489 + default: 490 + DEBUG_ERR("%s unknown/unsupported keytype %u\n", 491 + __func__, t->keytype); 492 + return -EINVAL; 493 + } 494 + 495 + if (t->len != keylen) { 496 + DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n", 497 + __func__, t->len); 498 + return -EINVAL; 499 + } 500 + 501 + /* only one path possible: via PCKMO instruction */ 502 + rc = pkey_clr2protkey(t->keytype, t->clearkey, 503 + protkey, protkeylen, protkeytype); 504 + if (rc) { 505 + DEBUG_ERR("%s unable to build protected key from clear", 506 + __func__); 507 + } 508 + 509 + return rc; 510 + } 511 + 452 512 /* 453 513 * Transform a non-CCA key token into a protected key 454 514 */ ··· 561 411 u8 *protkey, u32 *protkeylen, u32 *protkeytype) 562 412 { 563 413 struct keytoken_header *hdr = (struct keytoken_header *)key; 564 - u8 *tmpbuf = NULL; 565 414 int rc = -EINVAL; 566 415 567 416 switch (hdr->version) { ··· 579 430 break; 580 431 } 581 432 case TOKVER_CLEAR_KEY: { 582 - struct clearaeskeytoken *t; 583 - struct pkey_clrkey ckey; 584 - union u_tmpbuf { 585 - u8 skey[SECKEYBLOBSIZE]; 586 - u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 587 - }; 588 - size_t tmpbuflen = sizeof(union u_tmpbuf); 433 + struct clearkeytoken *t = (struct clearkeytoken *)key; 589 434 590 - if (keylen < sizeof(struct clearaeskeytoken)) 435 + if (keylen < sizeof(struct clearkeytoken) || 436 + keylen != sizeof(*t) + t->len) 591 437 goto out; 592 - t = (struct clearaeskeytoken *)key; 593 - if (keylen != sizeof(*t) + t->len) 594 - goto out; 595 - if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) || 596 - (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) || 597 - (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 598 - memcpy(ckey.clrkey, t->clearkey, t->len); 599 - else 600 - goto out; 601 - /* alloc temp key buffer space */ 602 - tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 603 - if (!tmpbuf) { 604 - rc = -ENOMEM; 605 - goto out; 438 + switch (t->keytype) { 439 + case PKEY_KEYTYPE_AES_128: 440 + case PKEY_KEYTYPE_AES_192: 441 + case PKEY_KEYTYPE_AES_256: 442 + rc = nonccatokaes2pkey(t, protkey, 443 + protkeylen, protkeytype); 444 + break; 445 + case PKEY_KEYTYPE_ECC_P256: 446 + case PKEY_KEYTYPE_ECC_P384: 447 + case PKEY_KEYTYPE_ECC_P521: 448 + case PKEY_KEYTYPE_ECC_ED25519: 449 + case PKEY_KEYTYPE_ECC_ED448: 450 + rc = nonccatokecc2pkey(t, protkey, 451 + protkeylen, protkeytype); 452 + break; 453 + default: 454 + DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n", 455 + __func__, t->keytype); 456 + return -EINVAL; 606 457 } 607 - /* try direct way with the PCKMO instruction */ 608 - rc = pkey_clr2protkey(t->keytype, ckey.clrkey, 609 - protkey, protkeylen, protkeytype); 610 - if (rc == 0) 611 - break; 612 - /* PCKMO failed, so try the CCA secure key way */ 613 - zcrypt_wait_api_operational(); 614 - rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 615 - ckey.clrkey, tmpbuf); 616 - if (rc == 0) 617 - rc = pkey_skey2pkey(tmpbuf, 618 - protkey, protkeylen, protkeytype); 619 - if (rc == 0) 620 - break; 621 - /* if the CCA way also failed, let's try via EP11 */ 622 - rc = pkey_clr2ep11key(ckey.clrkey, t->len, 623 - tmpbuf, &tmpbuflen); 624 - if (rc == 0) 625 - rc = pkey_ep11key2pkey(tmpbuf, 626 - protkey, protkeylen, protkeytype); 627 - /* now we should really have an protected key */ 628 - DEBUG_ERR("%s unable to build protected key from clear", 629 - __func__); 630 458 break; 631 459 } 632 460 case TOKVER_EP11_AES: { ··· 626 500 default: 627 501 DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 628 502 __func__, hdr->version); 629 - rc = -EINVAL; 630 503 } 631 504 632 505 out: 633 - kfree(tmpbuf); 634 506 return rc; 635 507 } 636 508 ··· 1273 1149 1274 1150 static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1275 1151 { 1276 - if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 1152 + if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) 1277 1153 return ERR_PTR(-EINVAL); 1278 1154 1279 1155 return memdup_user(ukey, keylen);