Commit 227a9197 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik
Browse files

s390/zcrypt: Rework MKVP fields and handling



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: default avatarHarald Freudenberger <freude@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent ecd2fd11
Loading
Loading
Loading
Loading
+26 −22
Original line number Diff line number Diff line
@@ -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;
		}
+17 −9
Original line number Diff line number Diff line
@@ -1708,8 +1708,8 @@ int cca_get_info(u16 cardnr, u16 domain, struct cca_info *ci, u32 xflags)
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)
+12 −12
Original line number Diff line number Diff line
@@ -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 */
+68 −42
Original line number Diff line number Diff line
@@ -103,6 +103,16 @@ static const struct attribute_group cca_card_attr_grp = {
	.attrs = cca_card_attrs,
};

/*
 * 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
 */
@@ -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;
}