From d48f194e6be940ba304496f8006cc70060f3bda65d8260835b9b612de097e483 Mon Sep 17 00:00:00 2001 From: Nikolay Gueorguiev Date: Tue, 10 Oct 2023 08:22:26 +0000 Subject: [PATCH] Accepting request 1116617 from home:ngueorguiev:branches:Base:System Applied a patch (jsc#PED-6373) OBS-URL: https://build.opensuse.org/request/show/1116617 OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=180 --- _service | 15 +- ...1-AES-keys-with-prepended-header-to-.patch | 691 ++++++++++++++++++ s390-tools.changes | 6 + s390-tools.spec | 2 + vendor.tar.gz | 4 +- 5 files changed, 707 insertions(+), 11 deletions(-) create mode 100644 s390-tools-sles15sp6-zkey-Support-EP11-AES-keys-with-prepended-header-to-.patch diff --git a/_service b/_service index bc6bf7b..fbee1b9 100644 --- a/_service +++ b/_service @@ -1,15 +1,12 @@ - + s390-tools-2.29.0.tar.gz zst + s390-tools/rust/pv/Cargo.toml + s390-tools/rust/pv/openssl_extentions/Cargo.toml + s390-tools/rust/utils/Cargo.toml + s390-tools/rust/pvsecret/Cargo.toml true - ../../vendor - /rust/pvsecret/Cargo.toml - /rust/pv/Cargo.toml - /rust/pv/openssl_extentions/Cargo.toml - /rust/utils/Cargo.toml - - - s390-tools-2.29.0.tar.gz + diff --git a/s390-tools-sles15sp6-zkey-Support-EP11-AES-keys-with-prepended-header-to-.patch b/s390-tools-sles15sp6-zkey-Support-EP11-AES-keys-with-prepended-header-to-.patch new file mode 100644 index 0000000..a36ac96 --- /dev/null +++ b/s390-tools-sles15sp6-zkey-Support-EP11-AES-keys-with-prepended-header-to-.patch @@ -0,0 +1,691 @@ +--- + zkey/ep11.c | 48 +++++++++++----- + zkey/keystore.c | 4 + + zkey/kmip/zkey-kmip.c | 74 +++++++++++++++++++++---- + zkey/kms.c | 9 ++- + zkey/pkey.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++-- + zkey/pkey.h | 45 +++++++++++---- + zkey/zkey-cryptsetup.c | 15 ++++- + zkey/zkey.c | 8 ++ + 8 files changed, 294 insertions(+), 50 deletions(-) + +--- a/zkey/ep11.c ++++ b/zkey/ep11.c +@@ -365,8 +365,9 @@ int select_ep11_apqn_by_mkvp(struct ep11 + * @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 + */ + 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 ep1 + 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 ep1 + } + + 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 + 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 + 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; +--- a/zkey/keystore.c ++++ b/zkey/keystore.c +@@ -3398,7 +3398,9 @@ static int _keystore_perform_reencipher( + "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"); + } +--- a/zkey/kmip/zkey-kmip.c ++++ b/zkey/kmip/zkey-kmip.c +@@ -5278,9 +5278,11 @@ static int _ep11_unwrap_key_rsa(struct p + 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 p + 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 p + 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; ++ /* 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", +- ep11key->head.keybitlen); ++ 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; + } +--- a/zkey/kms.c ++++ b/zkey/kms.c +@@ -2175,7 +2175,7 @@ int generate_kms_key(struct kms_info *km + 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 *km + 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_ + 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 + 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 " +--- a/zkey/pkey.c ++++ b/zkey/pkey.c +@@ -858,7 +858,7 @@ static enum pkey_key_type key_type_to_pk + 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 pke + 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_ + 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_ + 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_f + 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_f + 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( + 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( + 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,11 @@ bool is_ep11_aes_key(const u8 *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) +@@ -1605,6 +1661,65 @@ bool is_ep11_aes_key(const u8 *key, size + } + + /** ++ * 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) ++ return false; ++ ++ 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 + * + * @param[in] key the secure key token +@@ -1629,6 +1744,11 @@ bool is_xts_key(const u8 *key, size_t ke + 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 + 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 + *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, + 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 + 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); +--- 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( + 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); +--- 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; +--- 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"); + } diff --git a/s390-tools.changes b/s390-tools.changes index 7d2aec5..89f824d 100644 --- a/s390-tools.changes +++ b/s390-tools.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Oct 6 06:10:19 UTC 2023 - Nikolay Gueorguiev + +- Added a patch (jsc#PED-6373) + * s390-tools-sles15sp6-zkey-Support-EP11-AES-keys-with-prepended-header-to-.patch + ------------------------------------------------------------------- Mon Aug 28 15:52:15 UTC 2023 - Nikolay Gueorguiev diff --git a/s390-tools.spec b/s390-tools.spec index f0782c5..e139486 100644 --- a/s390-tools.spec +++ b/s390-tools.spec @@ -151,6 +151,8 @@ Patch909: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl Patch910: s390-tools-sles15sp1-11-zdev-Do-not-call-zipl-on-initrd-update.patch Patch911: s390-tools-sles15sp5-remove-no-pie-link-arguments.patch # +Patch912: s390-tools-sles15sp6-zkey-Support-EP11-AES-keys-with-prepended-header-to-.patch +# Patch999: s390-tools-ALP-zdev-live.patch # diff --git a/vendor.tar.gz b/vendor.tar.gz index d8bf27d..253cde9 100644 --- a/vendor.tar.gz +++ b/vendor.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d233de3dd3d74e7ce6fdedd99f6f0cc70ed80fe78b01c9321ca459ce06a7469c -size 37524839 +oid sha256:6fba8bcb49456ba6ef765899deaeed187324a7bfc90a76b4b718bbb502cecee7 +size 37525174