]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/pkey: Support new xflag PKEY_XFLAG_NOCLEARKEY
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 15 Jan 2026 12:00:24 +0000 (13:00 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sat, 31 Jan 2026 02:52:30 +0000 (10:52 +0800)
Introduce a new xflag PKEY_XFLAG_NOCLEARKEY which when given refuses
the conversion of "clear key tokens" to protected key material.

Some algorithms (PAES, PHMAC) have the need to construct "clear key
tokens" to be used during selftest. But in general these algorithms
should only support clear key material for testing purpose. So now the
algorithm implementation can signal via xflag PKEY_XFLAG_NOCLEARKEY
that a conversion of clear key material to protected key is not
acceptable and thus the pkey layer (usually one of the handler
modules) refuses clear key material with -EINVAL.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
arch/s390/include/asm/pkey.h
drivers/s390/crypto/pkey_cca.c
drivers/s390/crypto/pkey_ep11.c
drivers/s390/crypto/pkey_pckmo.c

index b7b59faf16f497a9c58ce2e15bf8d89d2b898c8a..0af5ac4f646bcf616130c2fca8b1d20eec7e164e 100644 (file)
@@ -21,7 +21,8 @@
  * @param keylen size of the key blob in bytes
  * @param protkey pointer to buffer receiving the protected key
  * @param xflags additional execution flags (see PKEY_XFLAG_* definitions below)
- *       As of now the only supported flag is PKEY_XFLAG_NOMEMALLOC.
+ *       As of now the only supported flags are PKEY_XFLAG_NOMEMALLOC
+ *       and PKEY_XFLAG_NOCLEARKEY.
  * @return 0 on success, negative errno value on failure
  */
 int pkey_key2protkey(const u8 *key, u32 keylen,
@@ -38,4 +39,9 @@ int pkey_key2protkey(const u8 *key, u32 keylen,
  */
 #define PKEY_XFLAG_NOMEMALLOC 0x0001
 
+/*
+ * Do not accept a clear key token as source for a protected key.
+ */
+#define PKEY_XFLAG_NOCLEARKEY 0x0002
+
 #endif /* _KAPI_PKEY_H */
index d4550d8d8eead966cbb97e9c05b3522a7cfbd4ef..9bfb518db893b144c276b24f51345b4c6957146c 100644 (file)
@@ -390,6 +390,11 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
        int i, len, rc;
        u32 xflags;
 
+       if (pflags & PKEY_XFLAG_NOCLEARKEY) {
+               PKEY_DBF_ERR("%s clear key but xflag NOCLEARKEY\n", __func__);
+               return -EINVAL;
+       }
+
        xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
 
        /* check keytype, subtype, clrkeylen, keybitsize */
index 654eed20d0d9beac07666f6d88d6a03fbe4eb971..f99c19323f3d7bf01b1f9d74e7cbed8d75cec89d 100644 (file)
@@ -358,6 +358,11 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
        int i, len, rc;
        u32 xflags;
 
+       if (pflags & PKEY_XFLAG_NOCLEARKEY) {
+               PKEY_DBF_ERR("%s clear key but xflag NOCLEARKEY\n", __func__);
+               return -EINVAL;
+       }
+
        xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
 
        /* check keytype, subtype, clrkeylen, keybitsize */
index 793326c4c59ad54d510bf10eb196667c7a124933..ea774ab8918064c29d51872918ccef1bc3c1a23b 100644 (file)
@@ -215,7 +215,8 @@ out:
 }
 
 static int pckmo_key2protkey(const u8 *key, u32 keylen,
-                            u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+                            u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+                            u32 xflags)
 {
        struct keytoken_header *hdr = (struct keytoken_header *)key;
        int rc = -EINVAL;
@@ -266,6 +267,11 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
                struct clearkeytoken *t = (struct clearkeytoken *)key;
                u32 keysize;
 
+               if (xflags & PKEY_XFLAG_NOCLEARKEY) {
+                       PKEY_DBF_ERR("%s clear key token but xflag NOCLEARKEY\n",
+                                    __func__);
+                       goto out;
+               }
                if (keylen < sizeof(*t) ||
                    keylen < sizeof(*t) + t->len)
                        goto out;
@@ -406,10 +412,10 @@ static int pkey_pckmo_key2protkey(const struct pkey_apqn *_apqns,
                                  size_t _nr_apqns,
                                  const u8 *key, u32 keylen,
                                  u8 *protkey, u32 *protkeylen, u32 *keyinfo,
-                                 u32 _xflags __always_unused)
+                                 u32 xflags)
 {
        return pckmo_key2protkey(key, keylen,
-                                protkey, protkeylen, keyinfo);
+                                protkey, protkeylen, keyinfo, xflags);
 }
 
 static int pkey_pckmo_gen_key(const struct pkey_apqn *_apqns, size_t _nr_apqns,