]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/zcrypt: Rework MKVP fields and handling
authorHarald Freudenberger <freude@linux.ibm.com>
Wed, 18 Mar 2026 16:41:31 +0000 (17:41 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 24 Mar 2026 20:00:42 +0000 (21:00 +0100)
In general all MKVPs (Master Key Verification Pattern) are binary
data - usually some kind of shortened hash value e.g. sha256.
Some code parts however used some u64 type which made compares
a little bit easier. Anyway this is binary data and so all
fields related to MKVP are now u8[] and function parameters
use (const) u8 * now. The sysfs emit for the MKVPs also has
been adapted to first format the MKVP as hex string into a
buffer and then use %s with sysfs_emit_at() to generate the
sysfs output. The patch also include a simple whitespace fix.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
drivers/s390/crypto/pkey_cca.c
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/crypto/zcrypt_ccamisc.h
drivers/s390/crypto/zcrypt_cex4.c

index 9bfb518db893b144c276b24f51345b4c6957146c..4bc47952324e0981583bdabb4a6f7341d781789e 100644 (file)
@@ -87,50 +87,52 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
        zcrypt_wait_api_operational();
 
        if (hdr->type == TOKTYPE_CCA_INTERNAL) {
-               u64 cur_mkvp = 0, old_mkvp = 0;
+               const u8 *ptr_cur_mkvp = NULL;
+               const u8 *ptr_old_mkvp = NULL;
                int minhwtype = ZCRYPT_CEX3C;
 
                if (hdr->version == TOKVER_CCA_AES) {
                        struct secaeskeytoken *t = (struct secaeskeytoken *)key;
 
                        if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
-                               cur_mkvp = t->mkvp;
+                               ptr_cur_mkvp = t->mkvp;
                        if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
-                               old_mkvp = t->mkvp;
+                               ptr_old_mkvp = t->mkvp;
                } else if (hdr->version == TOKVER_CCA_VLSC) {
                        struct cipherkeytoken *t = (struct cipherkeytoken *)key;
 
                        minhwtype = ZCRYPT_CEX6;
                        if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
-                               cur_mkvp = t->mkvp0;
+                               ptr_cur_mkvp = t->mkvp0;
                        if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
-                               old_mkvp = t->mkvp0;
+                               ptr_old_mkvp = t->mkvp0;
                } else {
                        /* unknown CCA internal token type */
                        return -EINVAL;
                }
                rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   minhwtype, AES_MK_SET,
-                                  cur_mkvp, old_mkvp, xflags);
+                                  ptr_cur_mkvp, ptr_old_mkvp, xflags);
                if (rc)
                        goto out;
 
        } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
                struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
-               u64 cur_mkvp = 0, old_mkvp = 0;
+               const u8 *ptr_cur_mkvp = NULL;
+               const u8 *ptr_old_mkvp = NULL;
 
                if (t->secid == 0x20) {
                        if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
-                               cur_mkvp = t->mkvp;
+                               ptr_cur_mkvp = t->mkvp;
                        if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
-                               old_mkvp = t->mkvp;
+                               ptr_old_mkvp = t->mkvp;
                } else {
                        /* unknown CCA internal 2 token type */
                        return -EINVAL;
                }
                rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   ZCRYPT_CEX7, APKA_MK_SET,
-                                  cur_mkvp, old_mkvp, xflags);
+                                  ptr_cur_mkvp, ptr_old_mkvp, xflags);
                if (rc)
                        goto out;
 
@@ -167,31 +169,33 @@ static int cca_apqns4type(enum pkey_key_type ktype,
        zcrypt_wait_api_operational();
 
        if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
-               u64 cur_mkvp = 0, old_mkvp = 0;
+               const u8 *ptr_cur_mkvp = NULL;
+               const u8 *ptr_old_mkvp = NULL;
                int minhwtype = ZCRYPT_CEX3C;
 
                if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
-                       cur_mkvp = *((u64 *)cur_mkvp);
+                       ptr_cur_mkvp = cur_mkvp;
                if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
-                       old_mkvp = *((u64 *)alt_mkvp);
+                       ptr_old_mkvp = alt_mkvp;
                if (ktype == PKEY_TYPE_CCA_CIPHER)
                        minhwtype = ZCRYPT_CEX6;
                rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   minhwtype, AES_MK_SET,
-                                  cur_mkvp, old_mkvp, xflags);
+                                  ptr_cur_mkvp, ptr_old_mkvp, xflags);
                if (rc)
                        goto out;
 
        } else if (ktype == PKEY_TYPE_CCA_ECC) {
-               u64 cur_mkvp = 0, old_mkvp = 0;
+               const u8 *ptr_cur_mkvp = NULL;
+               const u8 *ptr_old_mkvp = NULL;
 
                if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
-                       cur_mkvp = *((u64 *)cur_mkvp);
+                       ptr_cur_mkvp = cur_mkvp;
                if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
-                       old_mkvp = *((u64 *)alt_mkvp);
+                       ptr_old_mkvp = alt_mkvp;
                rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
                                   ZCRYPT_CEX7, APKA_MK_SET,
-                                  cur_mkvp, old_mkvp, xflags);
+                                  ptr_cur_mkvp, ptr_old_mkvp, xflags);
                if (rc)
                        goto out;
 
@@ -487,14 +491,14 @@ static int cca_verifykey(const u8 *key, u32 keylen,
                *keybitsize = t->bitsize;
                rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                   ZCRYPT_CEX3C, AES_MK_SET,
-                                  t->mkvp, 0, xflags);
+                                  t->mkvp, NULL, xflags);
                if (!rc)
                        *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
                if (rc == -ENODEV) {
                        nr_apqns = ARRAY_SIZE(apqns);
                        rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                           ZCRYPT_CEX3C, AES_MK_SET,
-                                          0, t->mkvp, xflags);
+                                          NULL, t->mkvp, xflags);
                        if (!rc)
                                *flags = PKEY_FLAGS_MATCH_ALT_MKVP;
                }
@@ -521,14 +525,14 @@ static int cca_verifykey(const u8 *key, u32 keylen,
                        *keybitsize = PKEY_SIZE_AES_256;
                rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                   ZCRYPT_CEX6, AES_MK_SET,
-                                  t->mkvp0, 0, xflags);
+                                  t->mkvp0, NULL, xflags);
                if (!rc)
                        *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
                if (rc == -ENODEV) {
                        nr_apqns = ARRAY_SIZE(apqns);
                        rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
                                           ZCRYPT_CEX6, AES_MK_SET,
-                                          0, t->mkvp0, xflags);
+                                          NULL, t->mkvp0, xflags);
                        if (!rc)
                                *flags = PKEY_FLAGS_MATCH_ALT_MKVP;
                }
index 573bad1d6d86c789810feebc83379c67810cb083..3727e0df9827ef6401807a66f9384a9c9430da14 100644 (file)
@@ -1708,8 +1708,8 @@ out:
 EXPORT_SYMBOL(cca_get_info);
 
 int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
-                 int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
-                 u32 xflags)
+                 int minhwtype, int mktype,
+                 const u8 *ptr_cur_mkvp, const u8 *ptr_old_mkvp, u32 xflags)
 {
        struct zcrypt_device_status_ext *device_status;
        int i, card, dom, curmatch, oldmatch;
@@ -1753,20 +1753,28 @@ int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
                /* check min hardware type */
                if (minhwtype > 0 && minhwtype > ci.hwtype)
                        continue;
-               if (cur_mkvp || old_mkvp) {
+               if (ptr_cur_mkvp || ptr_old_mkvp) {
                        /* check mkvps */
                        curmatch = oldmatch = 0;
                        if (mktype == AES_MK_SET) {
-                               if (cur_mkvp && cur_mkvp == ci.cur_aes_mkvp)
+                               if (ptr_cur_mkvp &&
+                                   !memcmp(ptr_cur_mkvp, ci.cur_aes_mkvp,
+                                           sizeof(ci.cur_aes_mkvp)))
                                        curmatch = 1;
-                               if (old_mkvp && ci.old_aes_mk_state == '2' &&
-                                   old_mkvp == ci.old_aes_mkvp)
+                               if (ptr_old_mkvp &&
+                                   ci.old_aes_mk_state == '2' &&
+                                   !memcmp(ptr_old_mkvp, ci.old_aes_mkvp,
+                                           sizeof(ci.old_aes_mkvp)))
                                        oldmatch = 1;
                        } else {
-                               if (cur_mkvp && cur_mkvp == ci.cur_apka_mkvp)
+                               if (ptr_cur_mkvp &&
+                                   !memcmp(ptr_cur_mkvp, ci.cur_apka_mkvp,
+                                           sizeof(ci.cur_apka_mkvp)))
                                        curmatch = 1;
-                               if (old_mkvp && ci.old_apka_mk_state == '2' &&
-                                   old_mkvp == ci.old_apka_mkvp)
+                               if (ptr_old_mkvp &&
+                                   ci.old_apka_mk_state == '2' &&
+                                   !memcmp(ptr_old_mkvp, ci.old_apka_mkvp,
+                                           sizeof(ci.old_apka_mkvp)))
                                        oldmatch = 1;
                        }
                        if (curmatch + oldmatch < 1)
index 1ecc4e37e9ad3b4c3327fb39f9787b1ce3ae3fc2..06507363947b4a88bf270d99b20dd38615287923 100644 (file)
@@ -47,7 +47,7 @@ struct secaeskeytoken {
        u8  res1[1];
        u8  flag;     /* key flags */
        u8  res2[1];
-       u64 mkvp;     /* master key verification pattern */
+       u8  mkvp[8];  /* master key verification pattern */
        u8  key[32];  /* key value (encrypted) */
        u8  cv[8];    /* control vector */
        u16 bitsize;  /* key bit size */
@@ -64,8 +64,8 @@ struct cipherkeytoken {
        u8  res1[3];
        u8  kms;      /* key material state, 0x03 means wrapped with MK */
        u8  kvpt;     /* key verification pattern type, should be 0x01 */
-       u64 mkvp0;    /* master key verification pattern, lo part */
-       u64 mkvp1;    /* master key verification pattern, hi part (unused) */
+       u8  mkvp0[8]; /* master key verification pattern, lo part */
+       u8  mkvp1[8]; /* master key verification pattern, hi part (unused) */
        u8  eskwm;    /* encrypted section key wrapping method */
        u8  hashalg;  /* hash algorithmus used for wrapping key */
        u8  plfver;   /* pay load format version */
@@ -113,7 +113,7 @@ struct eccprivkeytoken {
        u8  ksrc;     /* key source */
        u16 pbitlen;  /* length of prime p in bits */
        u16 ibmadlen; /* IBM associated data length in bytes */
-       u64 mkvp;     /* master key verification pattern */
+       u8  mkvp[8];  /* master key verification pattern */
        u8  opk[48];  /* encrypted object protection key data */
        u16 adatalen; /* associated data length in bytes */
        u16 fseclen;  /* formatted section length in bytes */
@@ -227,8 +227,8 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
  * If no apqn meeting the criteria is found, -ENODEV is returned.
  */
 int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
-                 int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
-                 u32 xflags);
+                 int minhwtype, int mktype,
+                 const u8 *cur_mkvp, const u8 *old_mkvp, u32 xflags);
 
 #define AES_MK_SET  0
 #define APKA_MK_SET 1
@@ -245,12 +245,12 @@ struct cca_info {
        char new_asym_mk_state; /* '1' empty, '2' partially full, '3' full */
        char cur_asym_mk_state; /* '1' invalid, '2' valid */
        char old_asym_mk_state; /* '1' invalid, '2' valid */
-       u64  new_aes_mkvp;      /* truncated sha256 of new aes master key */
-       u64  cur_aes_mkvp;      /* truncated sha256 of current aes master key */
-       u64  old_aes_mkvp;      /* truncated sha256 of old aes master key */
-       u64  new_apka_mkvp;     /* truncated sha256 of new apka master key */
-       u64  cur_apka_mkvp;     /* truncated sha256 of current apka mk */
-       u64  old_apka_mkvp;     /* truncated sha256 of old apka mk */
+       u8   new_aes_mkvp[8];   /* truncated sha256 of new aes master key */
+       u8   cur_aes_mkvp[8];   /* truncated sha256 of current aes master key */
+       u8   old_aes_mkvp[8];   /* truncated sha256 of old aes master key */
+       u8   new_apka_mkvp[8];  /* truncated sha256 of new apka master key */
+       u8   cur_apka_mkvp[8];  /* truncated sha256 of current apka mk */
+       u8   old_apka_mkvp[8];  /* truncated sha256 of old apka mk */
        u8   new_asym_mkvp[16]; /* verify pattern of new asym master key */
        u8   cur_asym_mkvp[16]; /* verify pattern of current asym master key */
        u8   old_asym_mkvp[16]; /* verify pattern of old asym master key */
index e9a984903bffb7901bd0b33e2bc2e810440d2954..7080de18ff7b6d2c9ba1a533140ad480655307d0 100644 (file)
@@ -103,9 +103,19 @@ static const struct attribute_group cca_card_attr_grp = {
        .attrs = cca_card_attrs,
 };
 
- /*
-  * CCA queue additional device attributes
-  */
+/*
+ * Simple helper macro to format raw mkvp byte array into hex
+ */
+#define MKVP_TO_HEXBUF(mkvp, buf) \
+       do { \
+               BUILD_BUG_ON(sizeof(buf) <= 2 * sizeof(mkvp)); \
+               bin2hex(buf, mkvp, sizeof(mkvp)); \
+               buf[2 * sizeof(mkvp)] = '\0'; \
+       } while (0)
+
+/*
+ * CCA queue additional device attributes
+ */
 static ssize_t cca_mkvps_show(struct device *dev,
                              struct device_attribute *attr,
                              char *buf)
@@ -114,6 +124,7 @@ static ssize_t cca_mkvps_show(struct device *dev,
        static const char * const cao_state[] = { "invalid", "valid" };
        struct zcrypt_queue *zq = dev_get_drvdata(dev);
        struct cca_info ci;
+       char hexbuf[2 * 16 + 1];
        int n = 0;
 
        memset(&ci, 0, sizeof(ci));
@@ -122,71 +133,86 @@ static ssize_t cca_mkvps_show(struct device *dev,
                     AP_QID_QUEUE(zq->queue->qid),
                     &ci, 0);
 
-       if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3')
-               n += sysfs_emit_at(buf, n, "AES NEW: %s 0x%016llx\n",
+       if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') {
+               MKVP_TO_HEXBUF(ci.new_aes_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "AES NEW: %s 0x%s\n",
                                   new_state[ci.new_aes_mk_state - '1'],
-                                  ci.new_aes_mkvp);
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "AES NEW: - -\n");
+       }
 
-       if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2')
-               n += sysfs_emit_at(buf, n, "AES CUR: %s 0x%016llx\n",
+       if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2') {
+               MKVP_TO_HEXBUF(ci.cur_aes_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "AES CUR: %s 0x%s\n",
                                   cao_state[ci.cur_aes_mk_state - '1'],
-                                  ci.cur_aes_mkvp);
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "AES CUR: - -\n");
+       }
 
-       if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2')
-               n += sysfs_emit_at(buf, n, "AES OLD: %s 0x%016llx\n",
+       if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2') {
+               MKVP_TO_HEXBUF(ci.old_aes_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "AES OLD: %s 0x%s\n",
                                   cao_state[ci.old_aes_mk_state - '1'],
-                                  ci.old_aes_mkvp);
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "AES OLD: - -\n");
+       }
 
-       if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3')
-               n += sysfs_emit_at(buf, n, "APKA NEW: %s 0x%016llx\n",
+       if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3') {
+               MKVP_TO_HEXBUF(ci.new_apka_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "APKA NEW: %s 0x%s\n",
                                   new_state[ci.new_apka_mk_state - '1'],
-                                  ci.new_apka_mkvp);
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "APKA NEW: - -\n");
+       }
 
-       if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2')
-               n += sysfs_emit_at(buf, n, "APKA CUR: %s 0x%016llx\n",
+       if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2') {
+               MKVP_TO_HEXBUF(ci.cur_apka_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "APKA CUR: %s 0x%s\n",
                                   cao_state[ci.cur_apka_mk_state - '1'],
-                                  ci.cur_apka_mkvp);
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "APKA CUR: - -\n");
+       }
 
-       if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2')
-               n += sysfs_emit_at(buf, n, "APKA OLD: %s 0x%016llx\n",
+       if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2') {
+               MKVP_TO_HEXBUF(ci.old_apka_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "APKA OLD: %s 0x%s\n",
                                   cao_state[ci.old_apka_mk_state - '1'],
-                                  ci.old_apka_mkvp);
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "APKA OLD: - -\n");
+       }
 
-       if (ci.new_asym_mk_state >= '1' && ci.new_asym_mk_state <= '3')
-               n += sysfs_emit_at(buf, n, "ASYM NEW: %s 0x%016llx%016llx\n",
+       if (ci.new_asym_mk_state >= '1' && ci.new_asym_mk_state <= '3') {
+               MKVP_TO_HEXBUF(ci.new_asym_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "ASYM NEW: %s 0x%s\n",
                                   new_state[ci.new_asym_mk_state - '1'],
-                                  *((u64 *)(ci.new_asym_mkvp)),
-                                  *((u64 *)(ci.new_asym_mkvp + sizeof(u64))));
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "ASYM NEW: - -\n");
+       }
 
-       if (ci.cur_asym_mk_state >= '1' && ci.cur_asym_mk_state <= '2')
-               n += sysfs_emit_at(buf, n, "ASYM CUR: %s 0x%016llx%016llx\n",
+       if (ci.cur_asym_mk_state >= '1' && ci.cur_asym_mk_state <= '2') {
+               MKVP_TO_HEXBUF(ci.cur_asym_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "ASYM CUR: %s 0x%s\n",
                                   cao_state[ci.cur_asym_mk_state - '1'],
-                                  *((u64 *)(ci.cur_asym_mkvp)),
-                                  *((u64 *)(ci.cur_asym_mkvp + sizeof(u64))));
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "ASYM CUR: - -\n");
+       }
 
-       if (ci.old_asym_mk_state >= '1' && ci.old_asym_mk_state <= '2')
-               n += sysfs_emit_at(buf, n, "ASYM OLD: %s 0x%016llx%016llx\n",
+       if (ci.old_asym_mk_state >= '1' && ci.old_asym_mk_state <= '2') {
+               MKVP_TO_HEXBUF(ci.old_asym_mkvp, hexbuf);
+               n += sysfs_emit_at(buf, n, "ASYM OLD: %s 0x%s\n",
                                   cao_state[ci.old_asym_mk_state - '1'],
-                                  *((u64 *)(ci.old_asym_mkvp)),
-                                  *((u64 *)(ci.old_asym_mkvp + sizeof(u64))));
-       else
+                                  hexbuf);
+       } else {
                n += sysfs_emit_at(buf, n, "ASYM OLD: - -\n");
+       }
 
        return n;
 }