Commit bbecb519 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Heiko Carstens
Browse files

s390/pkey: Simplify protected key length calculation code



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: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 55e055ba
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -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:
 */
+36 −118
Original line number Diff line number Diff line
@@ -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;
			}
		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)
				goto out;
			break;
		default:
			PKEY_DBF_ERR("%s protected key token: unknown keytype %u\n",
				     __func__, t->keytype);
			if (t->len != keysize + AES_WK_VP_SIZE ||
			    keylen != sizeof(*t) + keysize + AES_WK_VP_SIZE)
				goto out;
			break;
		}
		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 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,

/*
 * 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);