From patchwork Wed Sep 6 13:30:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Heimes X-Patchwork-Id: 1830409 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=canonical.com header.i=@canonical.com header.a=rsa-sha256 header.s=20210705 header.b=T9LFnsIk; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Rgjtf2ZfNz1yhc for ; Wed, 6 Sep 2023 23:30:50 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1qdscE-00011L-IX; Wed, 06 Sep 2023 13:30:42 +0000 Received: from smtp-relay-canonical-1.internal ([10.131.114.174] helo=smtp-relay-canonical-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1qdscC-00010t-53 for kernel-team@lists.ubuntu.com; Wed, 06 Sep 2023 13:30:40 +0000 Received: from localhost.localdomain (dslb-094-217-141-215.094.217.pools.vodafone-ip.de [94.217.141.215]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-1.canonical.com (Postfix) with ESMTPSA id 3F7663F716 for ; Wed, 6 Sep 2023 13:30:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1694007039; bh=C/eDqUlgh/vD6VcVwXCiIbsyAotBiqeiepFXpXuXPYk=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=T9LFnsIkvKW3gunogCYmNb6hVQhyc3AS0XchnBW8fXxZOPKEPkqxhyelIkaQy3SYV /pl99wMPokSGog1FUhgdBEH/gwFTYJyjcjOhm8Iy77vi9HPck8ecVsEACDav8zch8L PIqmQnJ8NFYIpQ9YF2pKgWbjSlTGj/+y48h44h7zijxwEZfjo6C3htNELBPD3kZaqv XIpI7omkmnVGQx9cGUicNPD0EkSrtq5D8La1lq3fBnHxFGjqCyNR/nWlBxQkFQ7Hox ugsb0S5AoWDNrY4S1peJ0IWVSYuU3z5JsB4/BOp9DNr6CkLRwqCcceurCpQOCQ3Iwp /Yg4T0Fw/sMuQ== From: frank.heimes@canonical.com To: kernel-team@lists.ubuntu.com Subject: [M][PATCH 1/1] s390/zcrypt_ep11misc: support API ordinal 6 with empty pin-blob Date: Wed, 6 Sep 2023 15:30:31 +0200 Message-Id: <20230906133031.777653-2-frank.heimes@canonical.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230906133031.777653-1-frank.heimes@canonical.com> References: <20230906133031.777653-1-frank.heimes@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Holger Dengler BugLink: https://bugs.launchpad.net/bugs/2029390 Secure execution guest environments require an empty pinblob in all key generation and unwrap requests. Empty pinblobs are only available in EP11 API ordinal 6 or higher. Add an empty pinblob to key generation and unwrap requests, if the AP secure binding facility is available. In all other cases, stay with the empty pin tag (no pinblob) and the current API ordinals. The EP11 API ordinal also needs to be considered when the pkey module tries to figure out the list of eligible cards for key operations with protected keys in secure execution environment. These changes are transparent to userspace but required for running an secure execution guest with handling key generate and key derive (e.g. secure key to protected key) correct. Especially using EP11 secure keys with the kernel dm-crypt layer requires this patch. Co-developed-by: Harald Freudenberger Signed-off-by: Harald Freudenberger Signed-off-by: Holger Dengler Reviewed-by: Ingo Franzki Signed-off-by: Heiko Carstens (cherry picked from commit 386cb81e4ba7811573765aaaeb91b472639c2bae) Signed-off-by: Frank Heimes --- drivers/s390/crypto/ap_bus.c | 9 ++++ drivers/s390/crypto/ap_bus.h | 1 + drivers/s390/crypto/pkey_api.c | 27 ++++++++---- drivers/s390/crypto/zcrypt_ep11misc.c | 60 ++++++++++++++++++++------- drivers/s390/crypto/zcrypt_ep11misc.h | 4 +- 5 files changed, 76 insertions(+), 25 deletions(-) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 420120be300f..5fdadfa5195a 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -218,6 +218,15 @@ int ap_sb_available(void) return 0; } +/* + * ap_is_se_guest(): Check for SE guest with AP pass-through support. + */ +bool ap_is_se_guest(void) +{ + return is_prot_virt_guest() && ap_sb_available(); +} +EXPORT_SYMBOL(ap_is_se_guest); + /* * ap_fetch_qci_info(): Fetch cryptographic config info * diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 0d7b7eb374ad..4eb7dda4f976 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -289,6 +289,7 @@ void ap_flush_queue(struct ap_queue *aq); void *ap_airq_ptr(void); int ap_sb_available(void); +bool ap_is_se_guest(void); void ap_wait(enum ap_sm_wait wait); void ap_request_timeout(struct timer_list *t); void ap_bus_force_rescan(void); diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 396a159afdf5..6cfb6b2340c9 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -263,7 +263,9 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, /* build a list of apqns suitable for ep11 keys with cpacf support */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, NULL); + ZCRYPT_CEX7, + ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, + NULL); if (rc) goto out; @@ -299,7 +301,8 @@ static int pkey_ep11key2pkey(const u8 *key, size_t keylen, /* build a list of apqns suitable for this key */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, + ZCRYPT_CEX7, + ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, ep11_kb_wkvp(key, keylen)); if (rc) goto out; @@ -902,6 +905,7 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES) { struct ep11keyblob *kb = (struct ep11keyblob *)key; + int api; rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) @@ -911,8 +915,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, if (ksize) *ksize = kb->head.bitlen; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX7, EP11_API_V, + ZCRYPT_CEX7, api, ep11_kb_wkvp(key, keylen)); if (rc) goto out; @@ -926,6 +931,7 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES_WITH_HEADER) { struct ep11kblob_header *kh = (struct ep11kblob_header *)key; + int api; rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); @@ -936,8 +942,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, if (ksize) *ksize = kh->bitlen; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX7, EP11_API_V, + ZCRYPT_CEX7, api, ep11_kb_wkvp(key, keylen)); if (rc) goto out; @@ -1056,7 +1063,7 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, return -EINVAL; if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { minhwtype = ZCRYPT_CEX7; - api = EP11_API_V; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; } rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, minhwtype, api, kb->wkvp); @@ -1072,7 +1079,7 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, return -EINVAL; if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { minhwtype = ZCRYPT_CEX7; - api = EP11_API_V; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; } rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, minhwtype, api, kb->wkvp); @@ -1182,11 +1189,13 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, ktype == PKEY_TYPE_EP11_AES || ktype == PKEY_TYPE_EP11_ECC) { u8 *wkvp = NULL; + int api; if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) wkvp = cur_mkvp; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, wkvp); + ZCRYPT_CEX7, api, wkvp); if (rc) goto out; @@ -2160,7 +2169,9 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, /* build a list of apqns able to generate an cipher key */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, NULL); + ZCRYPT_CEX7, + ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, + NULL); if (rc) return rc; diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c index 669ad6f5d5b0..0a877f9792c2 100644 --- a/drivers/s390/crypto/zcrypt_ep11misc.c +++ b/drivers/s390/crypto/zcrypt_ep11misc.c @@ -29,6 +29,8 @@ #define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__) #define DEBUG_ERR(...) ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__) +#define EP11_PINBLOB_V1_BYTES 56 + /* default iv used here */ static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; @@ -592,7 +594,7 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, struct ep11_cprb *req = NULL, *rep = NULL; struct ep11_target_dev target; struct ep11_urb *urb = NULL; - int api = 1, rc = -ENOMEM; + int api = EP11_API_V1, rc = -ENOMEM; /* request cprb and payload */ req = alloc_cprb(sizeof(struct ep11_info_req_pl)); @@ -789,8 +791,7 @@ static int _ep11_genaeskey(u16 card, u16 domain, u32 attr_bool_bits; u32 attr_val_len_type; u32 attr_val_len_value; - u8 pin_tag; - u8 pin_len; + /* followed by empty pin tag or empty pinblob tag */ } __packed * req_pl; struct keygen_rep_pl { struct pl_head head; @@ -803,9 +804,11 @@ static int _ep11_genaeskey(u16 card, u16 domain, u8 data[512]; } __packed * rep_pl; struct ep11_cprb *req = NULL, *rep = NULL; + size_t req_pl_size, pinblob_size = 0; struct ep11_target_dev target; struct ep11_urb *urb = NULL; int api, rc = -ENOMEM; + u8 *p; switch (keybitsize) { case 128: @@ -821,12 +824,22 @@ static int _ep11_genaeskey(u16 card, u16 domain, } /* request cprb and payload */ - req = alloc_cprb(sizeof(struct keygen_req_pl)); + api = (!keygenflags || keygenflags & 0x00200000) ? + EP11_API_V4 : EP11_API_V1; + if (ap_is_se_guest()) { + /* + * genkey within SE environment requires API ordinal 6 + * with empty pinblob + */ + api = EP11_API_V6; + pinblob_size = EP11_PINBLOB_V1_BYTES; + } + req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size); + req = alloc_cprb(req_pl_size); if (!req) goto out; req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req)); - api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1; - prep_head(&req_pl->head, sizeof(*req_pl), api, 21); /* GenerateKey */ + prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */ req_pl->var_tag = 0x04; req_pl->var_len = sizeof(u32); req_pl->keybytes_tag = 0x04; @@ -842,7 +855,10 @@ static int _ep11_genaeskey(u16 card, u16 domain, req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */ req_pl->attr_val_len_value = keybitsize / 8; - req_pl->pin_tag = 0x04; + p = ((u8 *)req_pl) + sizeof(*req_pl); + /* pin tag */ + *p++ = 0x04; + *p++ = pinblob_size; /* reply cprb and payload */ rep = alloc_cprb(sizeof(struct keygen_rep_pl)); @@ -857,7 +873,7 @@ static int _ep11_genaeskey(u16 card, u16 domain, target.ap_id = card; target.dom_id = domain; prep_urb(urb, &target, 1, - req, sizeof(*req) + sizeof(*req_pl), + req, sizeof(*req) + req_pl_size, rep, sizeof(*rep) + sizeof(*rep_pl)); rc = zcrypt_send_ep11_cprb(urb); @@ -965,7 +981,7 @@ static int ep11_cryptsingle(u16 card, u16 domain, struct ep11_target_dev target; struct ep11_urb *urb = NULL; size_t req_pl_size, rep_pl_size; - int n, api = 1, rc = -ENOMEM; + int n, api = EP11_API_V1, rc = -ENOMEM; u8 *p; /* the simple asn1 coding used has length limits */ @@ -1084,7 +1100,7 @@ static int _ep11_unwrapkey(u16 card, u16 domain, * maybe followed by iv data * followed by kek tag + kek blob * followed by empty mac tag - * followed by empty pin tag + * followed by empty pin tag or empty pinblob tag * followed by encryted key tag + bytes */ } __packed * req_pl; @@ -1099,20 +1115,30 @@ static int _ep11_unwrapkey(u16 card, u16 domain, u8 data[512]; } __packed * rep_pl; struct ep11_cprb *req = NULL, *rep = NULL; + size_t req_pl_size, pinblob_size = 0; struct ep11_target_dev target; struct ep11_urb *urb = NULL; - size_t req_pl_size; int api, rc = -ENOMEM; u8 *p; /* request cprb and payload */ + api = (!keygenflags || keygenflags & 0x00200000) ? + EP11_API_V4 : EP11_API_V1; + if (ap_is_se_guest()) { + /* + * unwrap within SE environment requires API ordinal 6 + * with empty pinblob + */ + api = EP11_API_V6; + pinblob_size = EP11_PINBLOB_V1_BYTES; + } req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0) - + ASN1TAGLEN(keksize) + 4 + ASN1TAGLEN(enckeysize); + + ASN1TAGLEN(keksize) + ASN1TAGLEN(0) + + ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize); req = alloc_cprb(req_pl_size); if (!req) goto out; req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req)); - api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1; prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */ req_pl->attr_tag = 0x04; req_pl->attr_len = 7 * sizeof(u32); @@ -1137,9 +1163,10 @@ static int _ep11_unwrapkey(u16 card, u16 domain, /* empty mac key tag */ *p++ = 0x04; *p++ = 0; - /* empty pin tag */ + /* pin tag */ *p++ = 0x04; - *p++ = 0; + *p++ = pinblob_size; + p += pinblob_size; /* encrypted key value tag and bytes */ p += asn1tag_write(p, 0x04, enckey, enckeysize); @@ -1275,7 +1302,8 @@ static int _ep11_wrapkey(u16 card, u16 domain, if (!mech || mech == 0x80060001) req->flags |= 0x20; /* CPACF_WRAP needs special bit */ req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req)); - api = (!mech || mech == 0x80060001) ? 4 : 1; /* CKM_IBM_CPACF_WRAP */ + api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */ + EP11_API_V4 : EP11_API_V1; prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */ req_pl->var_tag = 0x04; req_pl->var_len = sizeof(u32); diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h index a0de1cccebbe..9d17fd5228a7 100644 --- a/drivers/s390/crypto/zcrypt_ep11misc.h +++ b/drivers/s390/crypto/zcrypt_ep11misc.h @@ -12,7 +12,9 @@ #include #include -#define EP11_API_V 4 /* highest known and supported EP11 API version */ +#define EP11_API_V1 1 /* min EP11 API, default if no higher api required */ +#define EP11_API_V4 4 /* supported EP11 API for the ep11misc cprbs */ +#define EP11_API_V6 6 /* min EP11 API for some cprbs in SE environment */ #define EP11_STRUCT_MAGIC 0x1234 #define EP11_BLOB_PKEY_EXTRACTABLE 0x00200000