]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/pkey: Simplify protected key length calculation code
authorHarald Freudenberger <freude@linux.ibm.com>
Fri, 25 Oct 2024 10:34:28 +0000 (12:34 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Tue, 29 Oct 2024 10:17:17 +0000 (11:17 +0100)
The calculation of the length of a protected key based on
the protected key type is scattered over certain places within
the pkey code. By introducing a new inline function
pkey_keytype_to_size() this can be centralized and the calling
code can be reduced and simplified.

With this also comes a slight rework of the generation of
protected keys. Now the pkey_pckmo module is able to generate
all but ECC keys.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
drivers/s390/crypto/pkey_base.h
drivers/s390/crypto/pkey_pckmo.c

index 7a1a5ce192d827a3a91a37302c55e2cf3992e41b..7347647dfaa768183e002a62702c56670200cc4a 100644 (file)
@@ -96,6 +96,42 @@ static inline u32 pkey_aes_bitsize_to_keytype(u32 keybitsize)
        }
 }
 
+/*
+ * helper function which translates the PKEY_KEYTYPE_*
+ * to the protected key size minus the WK VP length
+ */
+static inline u32 pkey_keytype_to_size(u32 keytype)
+{
+       switch (keytype) {
+       case PKEY_KEYTYPE_AES_128:
+               return 16;
+       case PKEY_KEYTYPE_AES_192:
+               return 24;
+       case PKEY_KEYTYPE_AES_256:
+               return 32;
+       case PKEY_KEYTYPE_ECC_P256:
+               return 32;
+       case PKEY_KEYTYPE_ECC_P384:
+               return 48;
+       case PKEY_KEYTYPE_ECC_P521:
+               return 80;
+       case PKEY_KEYTYPE_ECC_ED25519:
+               return 32;
+       case PKEY_KEYTYPE_ECC_ED448:
+               return 54;
+       case PKEY_KEYTYPE_AES_XTS_128:
+               return 32;
+       case PKEY_KEYTYPE_AES_XTS_256:
+               return 64;
+       case PKEY_KEYTYPE_HMAC_512:
+               return 64;
+       case PKEY_KEYTYPE_HMAC_1024:
+               return 128;
+       default:
+               return 0;
+       }
+}
+
 /*
  * pkey_api.c:
  */
index 70b9996e5f9f84bd829d9956a6e372c9adaceec0..20fabfff6ef8d471f923b040705ddcc296f9a51b 100644 (file)
@@ -37,23 +37,9 @@ static bool is_pckmo_key(const u8 *key, u32 keylen)
        case TOKTYPE_NON_CCA:
                switch (hdr->version) {
                case TOKVER_CLEAR_KEY:
-                       switch (t->keytype) {
-                       case PKEY_KEYTYPE_AES_128:
-                       case PKEY_KEYTYPE_AES_192:
-                       case PKEY_KEYTYPE_AES_256:
-                       case PKEY_KEYTYPE_ECC_P256:
-                       case PKEY_KEYTYPE_ECC_P384:
-                       case PKEY_KEYTYPE_ECC_P521:
-                       case PKEY_KEYTYPE_ECC_ED25519:
-                       case PKEY_KEYTYPE_ECC_ED448:
-                       case PKEY_KEYTYPE_AES_XTS_128:
-                       case PKEY_KEYTYPE_AES_XTS_256:
-                       case PKEY_KEYTYPE_HMAC_512:
-                       case PKEY_KEYTYPE_HMAC_1024:
+                       if (pkey_keytype_to_size(t->keytype))
                                return true;
-                       default:
-                               return false;
-                       }
+                       return false;
                case TOKVER_PROTECTED_KEY:
                        return true;
                default:
@@ -85,80 +71,49 @@ static int pckmo_clr2protkey(u32 keytype, const u8 *clrkey, u32 clrkeylen,
 
        int keysize, rc = -EINVAL;
        u8 paramblock[160];
-       u32 pkeytype;
-       long fc;
+       u32 pkeytype = 0;
+       unsigned int fc;
 
        switch (keytype) {
        case PKEY_KEYTYPE_AES_128:
-               /* 16 byte key, 32 byte aes wkvp, total 48 bytes */
-               keysize = 16;
-               pkeytype = keytype;
                fc = CPACF_PCKMO_ENC_AES_128_KEY;
                break;
        case PKEY_KEYTYPE_AES_192:
-               /* 24 byte key, 32 byte aes wkvp, total 56 bytes */
-               keysize = 24;
-               pkeytype = keytype;
                fc = CPACF_PCKMO_ENC_AES_192_KEY;
                break;
        case PKEY_KEYTYPE_AES_256:
-               /* 32 byte key, 32 byte aes wkvp, total 64 bytes */
-               keysize = 32;
-               pkeytype = keytype;
                fc = CPACF_PCKMO_ENC_AES_256_KEY;
                break;
        case PKEY_KEYTYPE_ECC_P256:
-               /* 32 byte key, 32 byte aes wkvp, total 64 bytes */
-               keysize = 32;
                pkeytype = PKEY_KEYTYPE_ECC;
                fc = CPACF_PCKMO_ENC_ECC_P256_KEY;
                break;
        case PKEY_KEYTYPE_ECC_P384:
-               /* 48 byte key, 32 byte aes wkvp, total 80 bytes */
-               keysize = 48;
                pkeytype = PKEY_KEYTYPE_ECC;
                fc = CPACF_PCKMO_ENC_ECC_P384_KEY;
                break;
        case PKEY_KEYTYPE_ECC_P521:
-               /* 80 byte key, 32 byte aes wkvp, total 112 bytes */
-               keysize = 80;
                pkeytype = PKEY_KEYTYPE_ECC;
                fc = CPACF_PCKMO_ENC_ECC_P521_KEY;
                break;
        case PKEY_KEYTYPE_ECC_ED25519:
-               /* 32 byte key, 32 byte aes wkvp, total 64 bytes */
-               keysize = 32;
                pkeytype = PKEY_KEYTYPE_ECC;
                fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY;
                break;
        case PKEY_KEYTYPE_ECC_ED448:
-               /* 64 byte key, 32 byte aes wkvp, total 96 bytes */
-               keysize = 64;
                pkeytype = PKEY_KEYTYPE_ECC;
                fc = CPACF_PCKMO_ENC_ECC_ED448_KEY;
                break;
        case PKEY_KEYTYPE_AES_XTS_128:
-               /* 2x16 byte keys, 32 byte aes wkvp, total 64 bytes */
-               keysize = 32;
-               pkeytype = PKEY_KEYTYPE_AES_XTS_128;
                fc = CPACF_PCKMO_ENC_AES_XTS_128_DOUBLE_KEY;
                break;
        case PKEY_KEYTYPE_AES_XTS_256:
-               /* 2x32 byte keys, 32 byte aes wkvp, total 96 bytes */
-               keysize = 64;
-               pkeytype = PKEY_KEYTYPE_AES_XTS_256;
                fc = CPACF_PCKMO_ENC_AES_XTS_256_DOUBLE_KEY;
                break;
        case PKEY_KEYTYPE_HMAC_512:
-               /* 64 byte key, 32 byte aes wkvp, total 96 bytes */
-               keysize = 64;
-               pkeytype = PKEY_KEYTYPE_HMAC_512;
                fc = CPACF_PCKMO_ENC_HMAC_512_KEY;
                break;
        case PKEY_KEYTYPE_HMAC_1024:
-               /* 128 byte key, 32 byte aes wkvp, total 160 bytes */
-               keysize = 128;
-               pkeytype = PKEY_KEYTYPE_HMAC_1024;
                fc = CPACF_PCKMO_ENC_HMAC_1024_KEY;
                break;
        default:
@@ -167,6 +122,9 @@ static int pckmo_clr2protkey(u32 keytype, const u8 *clrkey, u32 clrkeylen,
                goto out;
        }
 
+       keysize = pkey_keytype_to_size(keytype);
+       pkeytype = pkeytype ?: keytype;
+
        if (clrkeylen && clrkeylen < keysize) {
                PKEY_DBF_ERR("%s clear key size too small: %u < %d\n",
                             __func__, clrkeylen, keysize);
@@ -189,7 +147,8 @@ static int pckmo_clr2protkey(u32 keytype, const u8 *clrkey, u32 clrkeylen,
        }
        /* check for the pckmo subfunction we need now */
        if (!cpacf_test_func(&pckmo_functions, fc)) {
-               PKEY_DBF_ERR("%s pckmo functions not available\n", __func__);
+               PKEY_DBF_ERR("%s pckmo fc 0x%02x not available\n",
+                            __func__, fc);
                rc = -ENODEV;
                goto out;
        }
@@ -288,37 +247,33 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
        switch (hdr->version) {
        case TOKVER_PROTECTED_KEY: {
                struct protkeytoken *t = (struct protkeytoken *)key;
+               u32 keysize;
 
                if (keylen < sizeof(*t))
                        goto out;
+               keysize = pkey_keytype_to_size(t->keytype);
+               if (!keysize) {
+                       PKEY_DBF_ERR("%s protected key token: unknown keytype %u\n",
+                                    __func__, t->keytype);
+                       goto out;
+               }
                switch (t->keytype) {
                case PKEY_KEYTYPE_AES_128:
                case PKEY_KEYTYPE_AES_192:
                case PKEY_KEYTYPE_AES_256:
-                       if (keylen != sizeof(struct protaeskeytoken))
+                       if (t->len != keysize + AES_WK_VP_SIZE ||
+                           keylen != sizeof(struct protaeskeytoken))
                                goto out;
                        rc = pckmo_verify_protkey(t->protkey, t->len,
                                                  t->keytype);
                        if (rc)
                                goto out;
                        break;
-               case PKEY_KEYTYPE_AES_XTS_128:
-                       if (t->len != 64 || keylen != sizeof(*t) + t->len)
-                               goto out;
-                       break;
-               case PKEY_KEYTYPE_AES_XTS_256:
-               case PKEY_KEYTYPE_HMAC_512:
-                       if (t->len != 96 || keylen != sizeof(*t) + t->len)
-                               goto out;
-                       break;
-               case PKEY_KEYTYPE_HMAC_1024:
-                       if (t->len != 160 || keylen != sizeof(*t) + t->len)
+               default:
+                       if (t->len != keysize + AES_WK_VP_SIZE ||
+                           keylen != sizeof(*t) + keysize + AES_WK_VP_SIZE)
                                goto out;
                        break;
-               default:
-                       PKEY_DBF_ERR("%s protected key token: unknown keytype %u\n",
-                                    __func__, t->keytype);
-                       goto out;
                }
                memcpy(protkey, t->protkey, t->len);
                *protkeylen = t->len;
@@ -327,47 +282,12 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
        }
        case TOKVER_CLEAR_KEY: {
                struct clearkeytoken *t = (struct clearkeytoken *)key;
-               u32 keysize = 0;
+               u32 keysize;
 
                if (keylen < sizeof(struct clearkeytoken) ||
                    keylen != sizeof(*t) + t->len)
                        goto out;
-               switch (t->keytype) {
-               case PKEY_KEYTYPE_AES_128:
-               case PKEY_KEYTYPE_AES_192:
-               case PKEY_KEYTYPE_AES_256:
-                       keysize = pkey_keytype_aes_to_size(t->keytype);
-                       break;
-               case PKEY_KEYTYPE_ECC_P256:
-                       keysize = 32;
-                       break;
-               case PKEY_KEYTYPE_ECC_P384:
-                       keysize = 48;
-                       break;
-               case PKEY_KEYTYPE_ECC_P521:
-                       keysize = 80;
-                       break;
-               case PKEY_KEYTYPE_ECC_ED25519:
-                       keysize = 32;
-                       break;
-               case PKEY_KEYTYPE_ECC_ED448:
-                       keysize = 64;
-                       break;
-               case PKEY_KEYTYPE_AES_XTS_128:
-                       keysize = 32;
-                       break;
-               case PKEY_KEYTYPE_AES_XTS_256:
-                       keysize = 64;
-                       break;
-               case PKEY_KEYTYPE_HMAC_512:
-                       keysize = 64;
-                       break;
-               case PKEY_KEYTYPE_HMAC_1024:
-                       keysize = 128;
-                       break;
-               default:
-                       break;
-               }
+               keysize = pkey_keytype_to_size(t->keytype);
                if (!keysize) {
                        PKEY_DBF_ERR("%s clear key token: unknown keytype %u\n",
                                     __func__, t->keytype);
@@ -395,8 +315,6 @@ out:
 
 /*
  * Generate a random protected key.
- * Currently only the generation of AES protected keys
- * is supported.
  */
 static int pckmo_gen_protkey(u32 keytype, u32 subtype,
                             u8 *protkey, u32 *protkeylen, u32 *protkeytype)
@@ -405,32 +323,32 @@ static int pckmo_gen_protkey(u32 keytype, u32 subtype,
        int keysize;
        int rc;
 
+       keysize = pkey_keytype_to_size(keytype);
+       if (!keysize) {
+               PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
+                            __func__, keytype);
+               return -EINVAL;
+       }
+       if (subtype != PKEY_TYPE_PROTKEY) {
+               PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
+                            __func__, subtype);
+               return -EINVAL;
+       }
+
        switch (keytype) {
        case PKEY_KEYTYPE_AES_128:
        case PKEY_KEYTYPE_AES_192:
        case PKEY_KEYTYPE_AES_256:
-               keysize = pkey_keytype_aes_to_size(keytype);
-               break;
        case PKEY_KEYTYPE_AES_XTS_128:
-               keysize = 32;
-               break;
        case PKEY_KEYTYPE_AES_XTS_256:
        case PKEY_KEYTYPE_HMAC_512:
-               keysize = 64;
-               break;
        case PKEY_KEYTYPE_HMAC_1024:
-               keysize = 128;
                break;
        default:
-               PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
+               PKEY_DBF_ERR("%s unsupported keytype %d\n",
                             __func__, keytype);
                return -EINVAL;
        }
-       if (subtype != PKEY_TYPE_PROTKEY) {
-               PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
-                            __func__, subtype);
-               return -EINVAL;
-       }
 
        /* generate a dummy random clear key */
        get_random_bytes(clrkey, keysize);