- rebased to 2.29.0 (RHEL-11409)
- KVM: Support AP Bindings in SE Header (RHEL-10573) - KVM: Userspace Tool for IBK Request Generation and Insertion (RHEL-10579) - zkey: support for key type PKEY_TYPE_EP11_AES (RHEL-11441) - vmur: fix handling of option -t (RHEL-11479) - dbginfo.sh: global original Input Field Separator (IFS) (RHEL-16526) - Resolves: RHEL-11409 RHEL-10573 RHEL-10579 RHEL-11441 RHEL-11479 RHEL-16526
This commit is contained in:
		
							parent
							
								
									7dbe365154
								
							
						
					
					
						commit
						d799a95209
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										734
									
								
								s390utils-2.29.0-rhel.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										734
									
								
								s390utils-2.29.0-rhel.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,734 @@ | ||||
| From a32824922cb273703bacd44e6a29cbc33ae48cf5 Mon Sep 17 00:00:00 2001 | ||||
| From: Ingo Franzki <ifranzki@linux.ibm.com> | ||||
| Date: Fri, 21 Jul 2023 14:06:18 +0200 | ||||
| Subject: [PATCH] zkey: Support EP11 AES keys with prepended header to retain | ||||
|  EP11 session (RHEL-11440) | ||||
| 
 | ||||
| The pkey kernel module supports two key blob formats for EP11 AES keys. | ||||
| The first one (PKEY_TYPE_EP11) contains a 16 bytes header that overlays | ||||
| the first 32 bytes of the key blob which usually contain the ID of the | ||||
| EP11 session to which the key is bound. For zkey/dm-crypt that session | ||||
| ID used to be all zeros. The second blob format (PKEY_TYPE_EP11_AES) | ||||
| prepends the 16 bytes header to the blob, an thus does not overlay the | ||||
| blob. This format can be used for key blobs that are session-bound, i.e. | ||||
| have a non-zero session ID in the first 32 bytes. | ||||
| 
 | ||||
| Change zkey to generate EP11 keys using the new format (i.e. pkey type | ||||
| PKEY_TYPE_EP11_AES), but existing key blobs using the old format can | ||||
| still be used. | ||||
| 
 | ||||
| Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> | ||||
| Reviewed-by: Joerg Schmidbauer <jschmidb@de.ibm.com> | ||||
| Signed-off-by: Steffen Eiden <seiden@linux.ibm.com> | ||||
| (cherry picked from commit 1b044b8a40ab59e4f5ffe66e3ad81499b0beccce) | ||||
| ---
 | ||||
|  zkey/ep11.c            |  48 +++++++++----- | ||||
|  zkey/keystore.c        |   4 +- | ||||
|  zkey/kmip/zkey-kmip.c  |  76 ++++++++++++++++++---- | ||||
|  zkey/kms.c             |   9 ++- | ||||
|  zkey/pkey.c            | 141 +++++++++++++++++++++++++++++++++++++++-- | ||||
|  zkey/pkey.h            |  45 +++++++++---- | ||||
|  zkey/zkey-cryptsetup.c |  15 ++++- | ||||
|  zkey/zkey.c            |   8 ++- | ||||
|  8 files changed, 295 insertions(+), 51 deletions(-) | ||||
| 
 | ||||
| diff --git a/zkey/ep11.c b/zkey/ep11.c
 | ||||
| index 8359929..df8b57d 100644
 | ||||
| --- a/zkey/ep11.c
 | ||||
| +++ b/zkey/ep11.c
 | ||||
| @@ -365,8 +365,9 @@ int select_ep11_apqn_by_mkvp(struct ep11_lib *ep11, u8 *mkvp,
 | ||||
|   * @param[in] target    the target handle to use for the re-encipher operation | ||||
|   * @param[in] card      the card that corresponds to the target handle | ||||
|   * @param[in] domain    the domain that corresponds to the target handle | ||||
| - * @param[in/out] ep11key the EP11 key token to reencipher. The re-enciphered
 | ||||
| - *                      secure key will be returned in this buffer.
 | ||||
| + * @param[in/out] ep11key_blob the EP11 key token to reencipher. The
 | ||||
| + *                      re-enciphered secure key will be returned in this
 | ||||
| + *                      buffer.
 | ||||
|   * @param[in] ep11key_size the size of the secure key | ||||
|   * @param[in] verbose   if true, verbose messages are printed | ||||
|   * | ||||
| @@ -374,21 +375,29 @@ int select_ep11_apqn_by_mkvp(struct ep11_lib *ep11, u8 *mkvp,
 | ||||
|   */ | ||||
|  static int ep11_adm_reencrypt(struct ep11_lib *ep11, target_t target, | ||||
|  			      unsigned int card, unsigned int domain, | ||||
| -			      struct ep11keytoken *ep11key,
 | ||||
| +			      u8 *ep11key_blob,
 | ||||
|  			      unsigned int ep11key_size, bool verbose) | ||||
|  { | ||||
| +	struct ep11kblob_header *hdr = (struct ep11kblob_header *)ep11key_blob;
 | ||||
| +	struct ep11keytoken *ep11key;
 | ||||
|  	CK_BYTE resp[MAX_BLOBSIZE]; | ||||
|  	CK_BYTE req[MAX_BLOBSIZE]; | ||||
| -	char ep11_token_header[sizeof(ep11key->head)];
 | ||||
| +	char ep11_token_header[sizeof(ep11key->head)] = { 0 };
 | ||||
|  	struct XCPadmresp lrb; | ||||
|  	struct XCPadmresp rb; | ||||
| +	bool with_header;
 | ||||
|  	size_t resp_len; | ||||
|  	size_t blob_len; | ||||
|  	long req_len; | ||||
|  	CK_RV rv; | ||||
|  	int rc; | ||||
|   | ||||
| -	blob_len = ep11key->head.length;
 | ||||
| +	with_header = is_ep11_aes_key_with_header(ep11key_blob, ep11key_size);
 | ||||
| +	ep11key = (struct ep11keytoken *)(with_header ?
 | ||||
| +				ep11key_blob + sizeof(struct ep11kblob_header) :
 | ||||
| +				ep11key_blob);
 | ||||
| +	blob_len = with_header ? hdr->len - sizeof(struct ep11kblob_header) :
 | ||||
| +				 ep11key->head.len;
 | ||||
|  	if (blob_len > ep11key_size) { | ||||
|  		pr_verbose(verbose, "Blob length larger than secure key size"); | ||||
|  		return -EINVAL; | ||||
| @@ -397,9 +406,14 @@ static int ep11_adm_reencrypt(struct ep11_lib *ep11, target_t target,
 | ||||
|  	rb.domain = domain; | ||||
|  	lrb.domain = domain; | ||||
|   | ||||
| -	/* The token header is an overlay over the (all zero) session field */
 | ||||
| -	memcpy(ep11_token_header, ep11key, sizeof(ep11_token_header));
 | ||||
| -	memset(ep11key->session, 0, sizeof(ep11key->session));
 | ||||
| +	if (!with_header) {
 | ||||
| +		/*
 | ||||
| +		 * The token header is an overlay over the (all zero) session
 | ||||
| +		 * field
 | ||||
| +		 */
 | ||||
| +		memcpy(ep11_token_header, ep11key, sizeof(ep11_token_header));
 | ||||
| +		memset(ep11key->session, 0, sizeof(ep11key->session));
 | ||||
| +	}
 | ||||
|   | ||||
|  	resp_len = sizeof(resp); | ||||
|  	req_len = ep11->dll_xcpa_cmdblock(req, sizeof(req), XCP_ADM_REENCRYPT, | ||||
| @@ -446,7 +460,8 @@ static int ep11_adm_reencrypt(struct ep11_lib *ep11, target_t target,
 | ||||
|  	} | ||||
|   | ||||
|  	memcpy(ep11key, lrb.payload, blob_len); | ||||
| -	memcpy(ep11key, ep11_token_header, sizeof(ep11_token_header));
 | ||||
| +	if (!with_header)
 | ||||
| +		memcpy(ep11key, ep11_token_header, sizeof(ep11_token_header));
 | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| @@ -469,7 +484,6 @@ int reencipher_ep11_key(struct ep11_lib *ep11, target_t target,
 | ||||
|  			unsigned int card, unsigned int domain, u8 *secure_key, | ||||
|  			unsigned int secure_key_size, bool verbose) | ||||
|  { | ||||
| -	struct ep11keytoken *ep11key = (struct ep11keytoken *)secure_key;
 | ||||
|  	CK_IBM_DOMAIN_INFO dinf; | ||||
|  	CK_ULONG dinf_len = sizeof(dinf); | ||||
|  	CK_RV rv; | ||||
| @@ -493,17 +507,21 @@ int reencipher_ep11_key(struct ep11_lib *ep11, target_t target,
 | ||||
|  		return -ENODEV; | ||||
|  	} | ||||
|   | ||||
| -	rc = ep11_adm_reencrypt(ep11, target, card, domain, ep11key,
 | ||||
| +	rc = ep11_adm_reencrypt(ep11, target, card, domain, secure_key,
 | ||||
|  				secure_key_size, verbose); | ||||
|  	if (rc != 0) | ||||
|  		return rc; | ||||
|   | ||||
|  	if (is_xts_key(secure_key, secure_key_size)) { | ||||
| -		secure_key += EP11_KEY_SIZE;
 | ||||
| -		secure_key_size -= EP11_KEY_SIZE;
 | ||||
| -		ep11key = (struct ep11keytoken *)secure_key;
 | ||||
| +		if (is_ep11_aes_key_with_header(secure_key, secure_key_size)) {
 | ||||
| +			secure_key += EP11_AES_KEY_SIZE;
 | ||||
| +			secure_key_size -= EP11_AES_KEY_SIZE;
 | ||||
| +		} else {
 | ||||
| +			secure_key += EP11_KEY_SIZE;
 | ||||
| +			secure_key_size -= EP11_KEY_SIZE;
 | ||||
| +		}
 | ||||
|   | ||||
| -		rc = ep11_adm_reencrypt(ep11, target, card, domain, ep11key,
 | ||||
| +		rc = ep11_adm_reencrypt(ep11, target, card, domain, secure_key,
 | ||||
|  					secure_key_size, verbose); | ||||
|  		if (rc != 0) | ||||
|  			return rc; | ||||
| diff --git a/zkey/keystore.c b/zkey/keystore.c
 | ||||
| index 4efa2e4..c0a7037 100644
 | ||||
| --- a/zkey/keystore.c
 | ||||
| +++ b/zkey/keystore.c
 | ||||
| @@ -3398,7 +3398,9 @@ static int _keystore_perform_reencipher(struct keystore *keystore,
 | ||||
|  				      "CURRENT master key", name); | ||||
|  				if (!selected && | ||||
|  				    !is_ep11_aes_key(secure_key, | ||||
| -						     secure_key_size))
 | ||||
| +						     secure_key_size) &&
 | ||||
| +				    !is_ep11_aes_key_with_header(secure_key,
 | ||||
| +							secure_key_size))
 | ||||
|  					print_msg_for_cca_envvars( | ||||
|  							"secure AES key"); | ||||
|  			} | ||||
| diff --git a/zkey/kmip/zkey-kmip.c b/zkey/kmip/zkey-kmip.c
 | ||||
| index a00c5dd..e7b7c73 100644
 | ||||
| --- a/zkey/kmip/zkey-kmip.c
 | ||||
| +++ b/zkey/kmip/zkey-kmip.c
 | ||||
| @@ -5278,9 +5278,11 @@ static int _ep11_unwrap_key_rsa(struct plugin_handle *ph,
 | ||||
|  	m_UnwrapKey_t dll_m_UnwrapKey; | ||||
|  	const unsigned char *key_blob; | ||||
|  	struct ep11keytoken *ep11key; | ||||
| +	struct ep11kblob_header *hdr;
 | ||||
|  	CK_MECHANISM mech = { 0 }; | ||||
|  	CK_BYTE csum[7] = { 0 }; | ||||
|  	CK_BBOOL ck_true = true; | ||||
| +	int pkey_fd, rc;
 | ||||
|  	CK_RV rv; | ||||
|   | ||||
|  	CK_ATTRIBUTE template[] = { | ||||
| @@ -5306,7 +5308,8 @@ static int _ep11_unwrap_key_rsa(struct plugin_handle *ph,
 | ||||
|  	pr_verbose(&ph->pd, "Wrap hashing algorithm: %d", | ||||
|  		   ph->profile->wrap_hashing_algo); | ||||
|   | ||||
| -	if (*unwrapped_key_len < sizeof(struct ep11keytoken)) {
 | ||||
| +	if (*unwrapped_key_len < sizeof(struct ep11kblob_header) +
 | ||||
| +						sizeof(struct ep11keytoken)) {
 | ||||
|  		_set_error(ph, "Key buffer is too small"); | ||||
|  		return -EINVAL; | ||||
|  	} | ||||
| @@ -5381,19 +5384,68 @@ static int _ep11_unwrap_key_rsa(struct plugin_handle *ph,
 | ||||
|  		  256 * 256 * csum[csum_len - 3] + | ||||
|  		  256 * 256 * 256 * csum[csum_len - 4]; | ||||
|   | ||||
| -	/* Setup the EP11 token header */
 | ||||
| -	ep11key = (struct ep11keytoken *)unwrapped_key;
 | ||||
| -	memset(&ep11key->session, 0, sizeof(ep11key->session));
 | ||||
| -	ep11key->head.type = TOKEN_TYPE_NON_CCA;
 | ||||
| -	ep11key->head.length = *unwrapped_key_len;
 | ||||
| -	ep11key->head.version = TOKEN_VERSION_EP11_AES;
 | ||||
| -	ep11key->head.keybitlen = bit_len;
 | ||||
| -
 | ||||
| -	pr_verbose(&ph->pd, "unwrapped bit length: %u",
 | ||||
| -		   ep11key->head.keybitlen);
 | ||||
| +	/* Prepend and setup the EP11 token header */
 | ||||
| +	hdr = (struct ep11kblob_header *)unwrapped_key;
 | ||||
| +	ep11key = (struct ep11keytoken *)
 | ||||
| +			(unwrapped_key + sizeof(struct ep11kblob_header));
 | ||||
| +	memmove(ep11key, unwrapped_key, *unwrapped_key_len);
 | ||||
| +	*unwrapped_key_len += sizeof(struct ep11kblob_header);
 | ||||
| +	memset(hdr, 0, sizeof(struct ep11kblob_header));
 | ||||
| +	hdr->type = TOKEN_TYPE_NON_CCA;
 | ||||
| +	hdr->hver = 0;
 | ||||
| +	hdr->len = *unwrapped_key_len;
 | ||||
| +	hdr->version = TOKEN_VERSION_EP11_AES_WITH_HEADER;
 | ||||
| +	hdr->bitlen = bit_len;
 | ||||
| +
 | ||||
| +	pr_verbose(&ph->pd, "unwrapped bit length: %u", hdr->bitlen);
 | ||||
|   | ||||
|  	/* return full length, blob is already zero padded */ | ||||
| -	*unwrapped_key_len = sizeof(struct ep11keytoken);
 | ||||
| +	*unwrapped_key_len =
 | ||||
| +		sizeof(struct ep11kblob_header) + sizeof(struct ep11keytoken);
 | ||||
| +
 | ||||
| +	/*
 | ||||
| +	 * Check if the pkey module supports keys of type
 | ||||
| +	 * TOKEN_VERSION_EP11_AES_WITH_HEADER, older kernels may not support
 | ||||
| +	 * such keys. If it does not support such keys, convert the key to
 | ||||
| +	 * TOKEN_VERSION_EP11_AES type, if its session field is all zero
 | ||||
| +	 * (i.e. the key is not session bound).
 | ||||
| +	 */
 | ||||
| +	pkey_fd = open_pkey_device(ph->pd.verbose);
 | ||||
| +	if (pkey_fd < 0) {
 | ||||
| +		_set_error(ph, "Failed to open pkey device");
 | ||||
| +		return -EIO;
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	rc = validate_secure_key(pkey_fd, unwrapped_key, *unwrapped_key_len,
 | ||||
| +				 NULL, NULL, NULL, ph->pd.verbose);
 | ||||
| +	close(pkey_fd);
 | ||||
| +	if (rc == -EINVAL || rc == -ENODEV) {
 | ||||
| +		pr_verbose(&ph->pd, "The pkey kernel module does not support "
 | ||||
| +			   "PKEY_TYPE_EP11_AES, fall back to PKEY_TYPE_EP11");
 | ||||
| +
 | ||||
| +		if (is_ep11_key_session_bound(unwrapped_key,
 | ||||
| +					      *unwrapped_key_len)) {
 | ||||
| +			_set_error(ph, "The unwrapped key is session bound. "
 | ||||
| +				   "Kernel support is required for such keys");
 | ||||
| +			return -EIO;
 | ||||
| +		}
 | ||||
| +
 | ||||
| +		key_blob_len = hdr->len;
 | ||||
| +		*unwrapped_key_len -= sizeof(struct ep11kblob_header);
 | ||||
| +		memmove(unwrapped_key,
 | ||||
| +			unwrapped_key + sizeof(struct ep11kblob_header),
 | ||||
| +			*unwrapped_key_len);
 | ||||
| +		ep11key = (struct ep11keytoken *)unwrapped_key;
 | ||||
| +		memset(&ep11key->session, 0, sizeof(ep11key->session));
 | ||||
| +		ep11key->head.type = TOKEN_TYPE_NON_CCA;
 | ||||
| +		ep11key->head.len = key_blob_len -
 | ||||
| +						sizeof(struct ep11kblob_header);
 | ||||
| +		ep11key->head.version = TOKEN_VERSION_EP11_AES;
 | ||||
| +		ep11key->head.bitlen = bit_len;
 | ||||
| +	} else if (rc != 0) {
 | ||||
| +		_set_error(ph, "Failed to validate unwrapped key");
 | ||||
| +		return rc;
 | ||||
| +	}
 | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| diff --git a/zkey/kms.c b/zkey/kms.c
 | ||||
| index 9892a9e..2e33b22 100644
 | ||||
| --- a/zkey/kms.c
 | ||||
| +++ b/zkey/kms.c
 | ||||
| @@ -2175,7 +2175,7 @@ int generate_kms_key(struct kms_info *kms_info, const char *name,
 | ||||
|  	else if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) | ||||
|  		key_size = AESCIPHER_KEY_SIZE; | ||||
|  	else if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) | ||||
| -		key_size = EP11_KEY_SIZE;
 | ||||
| +		key_size = EP11_AES_KEY_SIZE;
 | ||||
|  	else | ||||
|  		return -ENOTSUP; | ||||
|   | ||||
| @@ -2248,6 +2248,9 @@ int generate_kms_key(struct kms_info *kms_info, const char *name,
 | ||||
|  	if (verbose) | ||||
|  		util_hexdump_grp(stderr, NULL, key_blob, 4, key_blob_size, 0); | ||||
|   | ||||
| +	if (is_ep11_aes_key(key_blob, key_blob_size))
 | ||||
| +		key_size = EP11_KEY_SIZE;
 | ||||
| +
 | ||||
|  	/* Save ID and label of 1st key */ | ||||
|  	rc = properties_set(key_props, xts ? PROP_NAME_KMS_XTS_KEY1_ID : | ||||
|  			    PROP_NAME_KMS_KEY_ID, key1_id); | ||||
| @@ -3132,6 +3135,8 @@ int import_kms_key(struct kms_info *kms_info, const char *key1_id,
 | ||||
|  		key_size =  AESCIPHER_KEY_SIZE; | ||||
|  	else if (is_ep11_aes_key(key_blob, key_blob_size)) | ||||
|  		key_size =  EP11_KEY_SIZE; | ||||
| +	else if (is_ep11_aes_key_with_header(key_blob, key_blob_size))
 | ||||
| +		key_size =  EP11_AES_KEY_SIZE;
 | ||||
|   | ||||
|  	if (key_size == 0 || key_blob_size > key_size) { | ||||
|  		pr_verbose(verbose, "Key '%s' has an unknown or unsupported " | ||||
| @@ -3366,6 +3371,8 @@ int refresh_kms_key(struct kms_info *kms_info, struct properties *key_props,
 | ||||
|  		key_size =  AESCIPHER_KEY_SIZE; | ||||
|  	else if (is_ep11_aes_key(key_blob, key_blob_size)) | ||||
|  		key_size =  EP11_KEY_SIZE; | ||||
| +	else if (is_ep11_aes_key_with_header(key_blob, key_blob_size))
 | ||||
| +		key_size =  EP11_AES_KEY_SIZE;
 | ||||
|   | ||||
|  	if (key_size == 0 || key_blob_size > key_size) { | ||||
|  		pr_verbose(verbose, "Key '%s' has an unknown or unsupported " | ||||
| diff --git a/zkey/pkey.c b/zkey/pkey.c
 | ||||
| index e013e06..2582088 100644
 | ||||
| --- a/zkey/pkey.c
 | ||||
| +++ b/zkey/pkey.c
 | ||||
| @@ -858,7 +858,7 @@ static enum pkey_key_type key_type_to_pkey_type(const char *key_type)
 | ||||
|  	if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) | ||||
|  		return PKEY_TYPE_CCA_CIPHER; | ||||
|  	if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) | ||||
| -		return PKEY_TYPE_EP11;
 | ||||
| +		return PKEY_TYPE_EP11_AES;
 | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| @@ -879,6 +879,8 @@ static size_t key_size_for_type(enum pkey_key_type type)
 | ||||
|  		return AESCIPHER_KEY_SIZE; | ||||
|  	case PKEY_TYPE_EP11: | ||||
|  		return EP11_KEY_SIZE; | ||||
| +	case PKEY_TYPE_EP11_AES:
 | ||||
| +		return EP11_AES_KEY_SIZE;
 | ||||
|  	default: | ||||
|  		return 0; | ||||
|  	} | ||||
| @@ -924,6 +926,7 @@ int generate_secure_key_random(int pkey_fd, const char *keyfile,
 | ||||
|  		return -ENOTSUP; | ||||
|  	} | ||||
|   | ||||
| +retry:
 | ||||
|  	genseck2.size = keybits_to_keysize(keybits); | ||||
|  	if (genseck2.size == 0) { | ||||
|  		warnx("Invalid value for '--keybits'/'-c': '%lu'", keybits); | ||||
| @@ -957,10 +960,33 @@ int generate_secure_key_random(int pkey_fd, const char *keyfile,
 | ||||
|  	genseck2.keylen = size; | ||||
|   | ||||
|  	rc = pkey_genseck2(pkey_fd, &genseck2, verbose); | ||||
| +	if (rc == -EINVAL && genseck2.type == PKEY_TYPE_EP11_AES) {
 | ||||
| +		/*
 | ||||
| +		 * Older kernels may not support gensek2 with key type
 | ||||
| +		 * PKEY_TYPE_EP11_AES, retry with PKEY_TYPE_EP11.
 | ||||
| +		 */
 | ||||
| +		pr_verbose(verbose,
 | ||||
| +			   "ioctl PKEY_GENSECK2 does not support "
 | ||||
| +			   "PKEY_TYPE_EP11_AES, fall back to PKEY_TYPE_EP11");
 | ||||
| +
 | ||||
| +		genseck2.type = PKEY_TYPE_EP11;
 | ||||
| +		free(genseck2.apqns);
 | ||||
| +		genseck2.apqns = NULL;
 | ||||
| +		genseck2.apqn_entries = 0;
 | ||||
| +		free(secure_key);
 | ||||
| +		goto retry;
 | ||||
| +	}
 | ||||
|  	if (rc != 0) { | ||||
|  		warnx("Failed to generate a secure key: %s", strerror(-rc)); | ||||
|  		goto out; | ||||
|  	} | ||||
| +	if (rc == 0 && genseck2.type == PKEY_TYPE_EP11) {
 | ||||
| +		if (is_ep11_key_session_bound(secure_key, size)) {
 | ||||
| +			warnx("The generated key is session bound. Kernel "
 | ||||
| +			      "support is required for such keys");
 | ||||
| +			goto out;
 | ||||
| +		}
 | ||||
| +	}
 | ||||
|   | ||||
|  	if (xts) { | ||||
|  		free(genseck2.apqns); | ||||
| @@ -1062,6 +1088,7 @@ int generate_secure_key_clear(int pkey_fd, const char *keyfile,
 | ||||
|  		return -ENOTSUP; | ||||
|  	} | ||||
|   | ||||
| +retry:
 | ||||
|  	clr2seck2.size = keybits_to_keysize(HALF_KEYSIZE_FOR_XTS( | ||||
|  						clear_key_size * 8, xts)); | ||||
|  	if (clr2seck2.size == 0) { | ||||
| @@ -1096,10 +1123,33 @@ int generate_secure_key_clear(int pkey_fd, const char *keyfile,
 | ||||
|  	clr2seck2.keylen = size; | ||||
|   | ||||
|  	rc = pkey_clr2seck2(pkey_fd, &clr2seck2, verbose); | ||||
| +	if (rc == -EINVAL && clr2seck2.type == PKEY_TYPE_EP11_AES) {
 | ||||
| +		/*
 | ||||
| +		 * Older kernels may not support clr2seck2 with key type
 | ||||
| +		 * PKEY_TYPE_EP11_AES, retry with PKEY_TYPE_EP11.
 | ||||
| +		 */
 | ||||
| +		pr_verbose(verbose,
 | ||||
| +			   "ioctl PKEY_CLR2SECK2 does not support "
 | ||||
| +			   "PKEY_TYPE_EP11_AES, fall back to PKEY_TYPE_EP11");
 | ||||
| +
 | ||||
| +		clr2seck2.type = PKEY_TYPE_EP11;
 | ||||
| +		free(clr2seck2.apqns);
 | ||||
| +		clr2seck2.apqns = NULL;
 | ||||
| +		clr2seck2.apqn_entries = 0;
 | ||||
| +		free(secure_key);
 | ||||
| +		goto retry;
 | ||||
| +	}
 | ||||
|  	if (rc != 0) { | ||||
|  		warnx("Failed to generate a secure key: %s", strerror(-rc)); | ||||
|  		goto out; | ||||
|  	} | ||||
| +	if (rc == 0 && clr2seck2.type == PKEY_TYPE_EP11) {
 | ||||
| +		if (is_ep11_key_session_bound(secure_key, size)) {
 | ||||
| +			warnx("The generated key is session bound. Kernel "
 | ||||
| +			      "support is required for such keys");
 | ||||
| +			goto out;
 | ||||
| +		}
 | ||||
| +	}
 | ||||
|   | ||||
|  	if (xts) { | ||||
|  		free(clr2seck2.apqns); | ||||
| @@ -1486,6 +1536,8 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size,
 | ||||
|  	struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key; | ||||
|  	struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key; | ||||
|  	struct ep11keytoken *ep11key = (struct ep11keytoken *)key; | ||||
| +	struct ep11keytoken *ep11key2 =
 | ||||
| +		(struct ep11keytoken *)(key + sizeof(struct ep11kblob_header));
 | ||||
|   | ||||
|  	util_assert(key != NULL, "Internal error: secure_key is NULL"); | ||||
|  	util_assert(mkvp != NULL, "Internal error: mkvp is NULL"); | ||||
| @@ -1497,6 +1549,8 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size,
 | ||||
|  		memcpy(mkvp, &cipherkey->kvp, sizeof(cipherkey->kvp)); | ||||
|  	else if (is_ep11_aes_key(key, key_size)) | ||||
|  		memcpy(mkvp, &ep11key->wkvp, sizeof(ep11key->wkvp)); | ||||
| +	else if (is_ep11_aes_key_with_header(key, key_size))
 | ||||
| +		memcpy(mkvp, &ep11key2->wkvp, sizeof(ep11key2->wkvp));
 | ||||
|  	else | ||||
|  		return -EINVAL; | ||||
|   | ||||
| @@ -1593,9 +1647,43 @@ bool is_ep11_aes_key(const u8 *key, size_t key_size)
 | ||||
|   | ||||
|  	if (ep11key->head.type != TOKEN_TYPE_NON_CCA) | ||||
|  		return false; | ||||
| +	if (ep11key->head.hver != 0)
 | ||||
| +		return false;
 | ||||
|  	if (ep11key->head.version != TOKEN_VERSION_EP11_AES) | ||||
|  		return false; | ||||
| -	if (ep11key->head.length > key_size)
 | ||||
| +	if (ep11key->head.len > key_size)
 | ||||
| +		return false;
 | ||||
| +
 | ||||
| +	if (ep11key->version != 0x1234)
 | ||||
| +		return false;
 | ||||
| +
 | ||||
| +	return true;
 | ||||
| +}
 | ||||
| +
 | ||||
| +/**
 | ||||
| + * Check if the specified key is a EP11 AES key token with external header.
 | ||||
| + *
 | ||||
| + * @param[in] key           the secure key token
 | ||||
| + * @param[in] key_size      the size of the secure key
 | ||||
| + *
 | ||||
| + * @returns true if the key is an EP11 AES token with external header type
 | ||||
| + */
 | ||||
| +bool is_ep11_aes_key_with_header(const u8 *key, size_t key_size)
 | ||||
| +{
 | ||||
| +	struct ep11kblob_header *header = (struct ep11kblob_header *)key;
 | ||||
| +	struct ep11keytoken *ep11key =
 | ||||
| +		(struct ep11keytoken *)(key + sizeof(struct ep11kblob_header));
 | ||||
| +
 | ||||
| +	if (key == NULL || key_size < EP11_AES_KEY_SIZE)
 | ||||
| +		return false;
 | ||||
| +
 | ||||
| +	if (header->type != TOKEN_TYPE_NON_CCA)
 | ||||
| +		return false;
 | ||||
| +	if (header->hver != 0)
 | ||||
| +		return false;
 | ||||
| +	if (header->version != TOKEN_VERSION_EP11_AES_WITH_HEADER)
 | ||||
| +		return false;
 | ||||
| +	if (header->len > key_size)
 | ||||
|  		return false; | ||||
|   | ||||
|  	if (ep11key->version != 0x1234) | ||||
| @@ -1604,6 +1692,33 @@ bool is_ep11_aes_key(const u8 *key, size_t key_size)
 | ||||
|  	return true; | ||||
|  } | ||||
|   | ||||
| +/**
 | ||||
| + * Check if the specified EP11 AES key is session bound.
 | ||||
| + *
 | ||||
| + * @param[in] key           the secure key token
 | ||||
| + * @param[in] key_size      the size of the secure key
 | ||||
| + *
 | ||||
| + * @returns true if the key is an EP11 AES token type
 | ||||
| + */
 | ||||
| +bool is_ep11_key_session_bound(const u8 *key, size_t key_size)
 | ||||
| +{
 | ||||
| +	struct ep11keytoken *ep11key;
 | ||||
| +
 | ||||
| +	if (is_ep11_aes_key(key, key_size)) {
 | ||||
| +		ep11key = (struct ep11keytoken *)key;
 | ||||
| +		return memcmp(ep11key->session + sizeof(ep11key->head),
 | ||||
| +			      ZERO_SESSION, sizeof(ep11key->session) -
 | ||||
| +					sizeof(ep11key->head)) != 0;
 | ||||
| +	} else if (is_ep11_aes_key_with_header(key, key_size)) {
 | ||||
| +		ep11key = (struct ep11keytoken *)
 | ||||
| +				(key + sizeof(struct ep11kblob_header));
 | ||||
| +		return memcmp(ep11key->session, ZERO_SESSION,
 | ||||
| +			      sizeof(ep11key->session)) != 0;
 | ||||
| +	} else {
 | ||||
| +		return false;
 | ||||
| +	}
 | ||||
| +}
 | ||||
| +
 | ||||
|  /** | ||||
|   * Check if the specified key is an XTS type key | ||||
|   * | ||||
| @@ -1629,6 +1744,11 @@ bool is_xts_key(const u8 *key, size_t key_size)
 | ||||
|  		    is_ep11_aes_key(key + EP11_KEY_SIZE, | ||||
|  					  key_size - EP11_KEY_SIZE)) | ||||
|  			return true; | ||||
| +	} else if (is_ep11_aes_key_with_header(key, key_size)) {
 | ||||
| +		if (key_size == 2 * EP11_AES_KEY_SIZE &&
 | ||||
| +		    is_ep11_aes_key_with_header(key + EP11_AES_KEY_SIZE,
 | ||||
| +						key_size - EP11_AES_KEY_SIZE))
 | ||||
| +			return true;
 | ||||
|  	} | ||||
|   | ||||
|  	return false; | ||||
| @@ -1650,6 +1770,7 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
 | ||||
|  	struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key; | ||||
|  	struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key; | ||||
|  	struct ep11keytoken *ep11key = (struct ep11keytoken *)key; | ||||
| +	struct ep11kblob_header *hdr = (struct ep11kblob_header *)key;
 | ||||
|   | ||||
|  	util_assert(bitsize != NULL, "Internal error: bitsize is NULL"); | ||||
|   | ||||
| @@ -1672,10 +1793,17 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
 | ||||
|  				*bitsize += cipherkey->pl - 384; | ||||
|  		} | ||||
|  	} else if (is_ep11_aes_key(key, key_size)) { | ||||
| -		*bitsize = ep11key->head.keybitlen;
 | ||||
| +		*bitsize = ep11key->head.bitlen;
 | ||||
|  		if (key_size == 2 * EP11_KEY_SIZE) { | ||||
|  			ep11key = (struct ep11keytoken *)(key + EP11_KEY_SIZE); | ||||
| -			*bitsize += ep11key->head.keybitlen;
 | ||||
| +			*bitsize += ep11key->head.bitlen;
 | ||||
| +		}
 | ||||
| +	} else if (is_ep11_aes_key_with_header(key, key_size)) {
 | ||||
| +		*bitsize = hdr->bitlen;
 | ||||
| +		if (key_size == 2 * EP11_AES_KEY_SIZE) {
 | ||||
| +			hdr = (struct ep11kblob_header *)
 | ||||
| +						(key + EP11_AES_KEY_SIZE);
 | ||||
| +			*bitsize += hdr->bitlen;
 | ||||
|  		} | ||||
|  	} else { | ||||
|  		return -EINVAL; | ||||
| @@ -1700,6 +1828,8 @@ const char *get_key_type(const u8 *key, size_t key_size)
 | ||||
|  		return KEY_TYPE_CCA_AESCIPHER; | ||||
|  	if (is_ep11_aes_key(key, key_size)) | ||||
|  		return KEY_TYPE_EP11_AES; | ||||
| +	if (is_ep11_aes_key_with_header(key, key_size))
 | ||||
| +		return KEY_TYPE_EP11_AES;
 | ||||
|  	return NULL; | ||||
|  } | ||||
|   | ||||
| @@ -2016,7 +2146,8 @@ int reencipher_secure_key(struct ext_lib *lib, u8 *secure_key,
 | ||||
|  		return rc; | ||||
|  	} | ||||
|   | ||||
| -	if (is_ep11_aes_key(secure_key, secure_key_size)) {
 | ||||
| +	if (is_ep11_aes_key(secure_key, secure_key_size) ||
 | ||||
| +	    is_ep11_aes_key_with_header(secure_key, secure_key_size)) {
 | ||||
|  		/* EP11 secure key: need the EP11 host library */ | ||||
|  		if (lib->ep11->lib_ep11 == NULL) { | ||||
|  			rc = load_ep11_library(lib->ep11, verbose); | ||||
| diff --git a/zkey/pkey.h b/zkey/pkey.h
 | ||||
| index 5a5bc3c..3b57c5f 100644
 | ||||
| --- a/zkey/pkey.h
 | ||||
| +++ b/zkey/pkey.h
 | ||||
| @@ -39,6 +39,8 @@ struct tokenheader {
 | ||||
|  #define TOKEN_VERSION_PROTECTED_KEY	0x01 | ||||
|  #define TOKEN_VERSION_CLEAR_KEY		0x02 | ||||
|  #define TOKEN_VERSION_EP11_AES		0x03 | ||||
| +#define TOKEN_VERSION_EP11_AES_WITH_HEADER	0x06
 | ||||
| +#define TOKEN_VERSION_EP11_ECC_WITH_HEADER	0x07
 | ||||
|   | ||||
|  struct aesdatakeytoken { | ||||
|  	u8  type;     /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ | ||||
| @@ -89,17 +91,20 @@ struct aescipherkeytoken {
 | ||||
|  	u8  varpart[80]; /* variable part */ | ||||
|  } __packed; | ||||
|   | ||||
| +struct ep11kblob_header {
 | ||||
| +	u8  type;	/* always 0x00 */
 | ||||
| +	u8  hver;	/* header version,  currently needs to be 0x00 */
 | ||||
| +	u16 len;	/* total length in bytes (including this header) */
 | ||||
| +	u8  version;	/* PKEY_TYPE_EP11_AES or PKEY_TYPE_EP11_ECC */
 | ||||
| +	u8  res0;	/* unused */
 | ||||
| +	u16 bitlen;	/* clear key bit len, 0 for unknown */
 | ||||
| +	u8  res1[8];	/* unused */
 | ||||
| +} __packed;
 | ||||
| +
 | ||||
|  struct ep11keytoken { | ||||
|  	union { | ||||
|  		u8 session[32]; | ||||
| -		struct {
 | ||||
| -			u8  type;      /* TOKEN_TYPE_NON_CCA (0x00) */
 | ||||
| -			u8  res0;      /* unused */
 | ||||
| -			u16 length;    /* length of token */
 | ||||
| -			u8  version;   /* TOKEN_VERSION_EP11_AES (0x03) */
 | ||||
| -			u8  res1;      /* unused */
 | ||||
| -			u16 keybitlen; /* clear key bit len, 0 for unknown */
 | ||||
| -		} head;
 | ||||
| +		struct ep11kblob_header head;
 | ||||
|  	}; | ||||
|  	u8  wkvp[16]; /* wrapping key verification pattern */ | ||||
|  	u64 attr;     /* boolean key attributes */ | ||||
| @@ -111,18 +116,29 @@ struct ep11keytoken {
 | ||||
|  	u8  padding[64]; | ||||
|  } __packed; | ||||
|   | ||||
| +#define ZERO_SESSION							\
 | ||||
| +	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 | ||||
| +
 | ||||
|  #define AESDATA_KEY_SIZE	sizeof(struct aesdatakeytoken) | ||||
|  #define AESCIPHER_KEY_SIZE	sizeof(struct aescipherkeytoken) | ||||
|  #define EP11_KEY_SIZE		sizeof(struct ep11keytoken) | ||||
| +#define EP11_AES_KEY_SIZE	(sizeof(struct ep11kblob_header) +	\
 | ||||
| +					sizeof(struct ep11keytoken))
 | ||||
|   | ||||
|  /* MAX/MIN from zt_common.h produces warnings for variable length arrays */ | ||||
|  #define _MIN(a, b)  ((a) < (b) ? (a) : (b)) | ||||
|  #define _MAX(a, b)  ((a) > (b) ? (a) : (b)) | ||||
|   | ||||
| -#define MAX_SECURE_KEY_SIZE	_MAX(EP11_KEY_SIZE, \
 | ||||
| -				     _MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE))
 | ||||
| -#define MIN_SECURE_KEY_SIZE	_MIN(EP11_KEY_SIZE, \
 | ||||
| -				     _MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE))
 | ||||
| +#define MAX_SECURE_KEY_SIZE	_MAX(					\
 | ||||
| +				     _MAX(EP11_KEY_SIZE,		\
 | ||||
| +					  EP11_AES_KEY_SIZE),		\
 | ||||
| +				     _MAX(AESDATA_KEY_SIZE,		\
 | ||||
| +					  AESCIPHER_KEY_SIZE))
 | ||||
| +#define MIN_SECURE_KEY_SIZE	_MIN(					\
 | ||||
| +				     _MIN(EP11_KEY_SIZE,		\
 | ||||
| +					  EP11_AES_KEY_SIZE),		\
 | ||||
| +				     _MIN(AESDATA_KEY_SIZE,		\
 | ||||
| +					  AESCIPHER_KEY_SIZE))
 | ||||
|   | ||||
|  struct pkey_seckey { | ||||
|  	u8  seckey[AESDATA_KEY_SIZE];  /* the secure key blob */ | ||||
| @@ -175,6 +191,9 @@ enum pkey_key_type {
 | ||||
|  	PKEY_TYPE_CCA_DATA   = (u32) 1, | ||||
|  	PKEY_TYPE_CCA_CIPHER = (u32) 2, | ||||
|  	PKEY_TYPE_EP11       = (u32) 3, | ||||
| +	PKEY_TYPE_CCA_ECC    = (u32) 0x1f,
 | ||||
| +	PKEY_TYPE_EP11_AES   = (u32) 6,
 | ||||
| +	PKEY_TYPE_EP11_ECC   = (u32) 7,
 | ||||
|  }; | ||||
|   | ||||
|  enum pkey_key_size { | ||||
| @@ -321,6 +340,8 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size,
 | ||||
|  bool is_cca_aes_data_key(const u8 *key, size_t key_size); | ||||
|  bool is_cca_aes_cipher_key(const u8 *key, size_t key_size); | ||||
|  bool is_ep11_aes_key(const u8 *key, size_t key_size); | ||||
| +bool is_ep11_aes_key_with_header(const u8 *key, size_t key_size);
 | ||||
| +bool is_ep11_key_session_bound(const u8 *key, size_t key_size);
 | ||||
|  bool is_xts_key(const u8 *key, size_t key_size); | ||||
|  int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize); | ||||
|  const char *get_key_type(const u8 *key, size_t key_size); | ||||
| diff --git a/zkey/zkey-cryptsetup.c b/zkey/zkey-cryptsetup.c
 | ||||
| index fae78c7..8b55f7d 100644
 | ||||
| --- a/zkey/zkey-cryptsetup.c
 | ||||
| +++ b/zkey/zkey-cryptsetup.c
 | ||||
| @@ -1673,7 +1673,10 @@ static int reencipher_prepare(int token)
 | ||||
|  				warnx("Failed to re-encipher the secure volume " | ||||
|  				      "key for device '%s'\n", g.pos_arg); | ||||
|  				if (!selected && | ||||
| -				    !is_ep11_aes_key((u8 *)key, securekeysize))
 | ||||
| +				    !is_ep11_aes_key((u8 *)key,
 | ||||
| +						     securekeysize) &&
 | ||||
| +				    !is_ep11_aes_key_with_header((u8 *)key,
 | ||||
| +								securekeysize))
 | ||||
|  					print_msg_for_cca_envvars( | ||||
|  						"secure AES volume key"); | ||||
|  				rc = -EINVAL; | ||||
| @@ -1696,7 +1699,10 @@ static int reencipher_prepare(int token)
 | ||||
|  				warnx("Failed to re-encipher the secure volume " | ||||
|  				      "key for device '%s'\n", g.pos_arg); | ||||
|  				if (!selected && | ||||
| -				    !is_ep11_aes_key((u8 *)key, securekeysize))
 | ||||
| +				    !is_ep11_aes_key((u8 *)key,
 | ||||
| +						     securekeysize) &&
 | ||||
| +				    !is_ep11_aes_key_with_header((u8 *)key,
 | ||||
| +								securekeysize))
 | ||||
|  					print_msg_for_cca_envvars( | ||||
|  						"secure AES volume key"); | ||||
|  				rc = -EINVAL; | ||||
| @@ -1836,7 +1842,10 @@ static int reencipher_complete(int token)
 | ||||
|  				warnx("Failed to re-encipher the secure volume " | ||||
|  				      "key for device '%s'\n", g.pos_arg); | ||||
|  				if (!selected && | ||||
| -				    !is_ep11_aes_key((u8 *)key, securekeysize))
 | ||||
| +				    !is_ep11_aes_key((u8 *)key,
 | ||||
| +						     securekeysize) &&
 | ||||
| +				    !is_ep11_aes_key_with_header((u8 *)key,
 | ||||
| +								securekeysize))
 | ||||
|  					print_msg_for_cca_envvars( | ||||
|  						"secure AES volume key"); | ||||
|  				rc = -EINVAL; | ||||
| diff --git a/zkey/zkey.c b/zkey/zkey.c
 | ||||
| index 3000290..843e554 100644
 | ||||
| --- a/zkey/zkey.c
 | ||||
| +++ b/zkey/zkey.c
 | ||||
| @@ -1968,7 +1968,9 @@ static int command_reencipher_file(void)
 | ||||
|  				      "master key has failed\n"); | ||||
|  				if (!selected && | ||||
|  				    !is_ep11_aes_key(secure_key, | ||||
| -						     secure_key_size))
 | ||||
| +						     secure_key_size) &&
 | ||||
| +				    !is_ep11_aes_key_with_header(secure_key,
 | ||||
| +							secure_key_size))
 | ||||
|  					print_msg_for_cca_envvars( | ||||
|  							"secure AES key"); | ||||
|  			} | ||||
| @@ -1993,7 +1995,9 @@ static int command_reencipher_file(void)
 | ||||
|  				      "master key has failed\n"); | ||||
|  				if (!selected && | ||||
|  				    !is_ep11_aes_key(secure_key, | ||||
| -						     secure_key_size))
 | ||||
| +						     secure_key_size) &&
 | ||||
| +				    !is_ep11_aes_key_with_header(secure_key,
 | ||||
| +							secure_key_size))
 | ||||
|  					print_msg_for_cca_envvars( | ||||
|  							"secure AES key"); | ||||
|  			} | ||||
| -- 
 | ||||
| 2.43.0 | ||||
| 
 | ||||
| @ -12,8 +12,8 @@ | ||||
| 
 | ||||
| Name:           s390utils | ||||
| Summary:        Utilities and daemons for IBM z Systems | ||||
| Version:        2.27.0 | ||||
| Release:        3%{?dist} | ||||
| Version:        2.29.0 | ||||
| Release:        1%{?dist} | ||||
| Epoch:          2 | ||||
| License:        MIT | ||||
| ExclusiveArch:  s390 s390x | ||||
| @ -127,6 +127,7 @@ popd | ||||
| %build | ||||
| make \ | ||||
|         CFLAGS="%{build_cflags}" CXXFLAGS="%{build_cxxflags}" LDFLAGS="%{build_ldflags}" \ | ||||
|         HAVE_CARGO=0 \ | ||||
|         HAVE_DRACUT=1 \ | ||||
| %if 0%{?with_pandoc} | ||||
|         ENABLE_DOC=1 \ | ||||
| @ -148,6 +149,7 @@ popd | ||||
| 
 | ||||
| %install | ||||
| make install \ | ||||
|         HAVE_CARGO=0 \ | ||||
|         HAVE_DRACUT=1 \ | ||||
| %if 0%{?with_pandoc} | ||||
|         ENABLE_DOC=1 \ | ||||
| @ -1004,6 +1006,15 @@ User-space development files for the s390/s390x architecture. | ||||
| 
 | ||||
| 
 | ||||
| %changelog | ||||
| * Mon Dec 04 2023 Dan Horák <dhorak@redhat.com> - 2:2.29.0-1 | ||||
| - rebased to 2.29.0 (RHEL-11409) | ||||
| - KVM: Support AP Bindings in SE Header (RHEL-10573) | ||||
| - KVM: Userspace Tool for IBK Request Generation and Insertion (RHEL-10579) | ||||
| - zkey: support for key type PKEY_TYPE_EP11_AES (RHEL-11441) | ||||
| - vmur: fix handling of option -t (RHEL-11479) | ||||
| - dbginfo.sh: global original Input Field Separator (IFS) (RHEL-16526) | ||||
| - Resolves: RHEL-11409 RHEL-10573 RHEL-10579 RHEL-11441 RHEL-11479 RHEL-16526 | ||||
| 
 | ||||
| * Mon Aug 07 2023 Dan Horák <dhorak@redhat.com> - 2:2.27.0-3 | ||||
| - zdev/dracut: fix kdump build to integrate with site support (#2229178) | ||||
| - Resolves: #2229178 | ||||
|  | ||||
							
								
								
									
										2
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sources
									
									
									
									
									
								
							| @ -1,3 +1,3 @@ | ||||
| SHA512 (cmsfs-1.1.8c.tar.gz) = 2ba5687d378fdd9871283728e81f1399047e74f9bba3936726eda11a978fe6ced1a300f15acb871d5daa26e61069d89767c753cf584f2731f5e99985db96aef0 | ||||
| SHA512 (src_vipa-2.1.0.tar.gz) = 8f6048e82b4bcc479dfb09d62da64b9519f66efc31889ff795ee6ca107e262167df57628c305f1b899c41bb3f035e6309552d8548c890855d319e8e60d6a6cf7 | ||||
| SHA512 (s390-tools-2.27.0.tar.gz) = 8ec83718639d17fe7b1990f4e492f1e1bdd11e814b7838c921733eeccb212f417141042118eadf1e8db498e3ff2ce0c8d404189e436cefe17d9a3dacea22429f | ||||
| SHA512 (s390-tools-2.29.0.tar.gz) = 3eeaab0e0c6559b9fb0b4c7cca49358a7cc7fe0cb11684d2d761fe105cc2bfd791d33ecc2070e3dfd877039b68e868699cd3cea318e64aee1cc0f348c7b41617 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user