From patchwork Thu Oct 20 23:55:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mat Martineau X-Patchwork-Id: 9387767 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8232E608A7 for ; Thu, 20 Oct 2016 23:55:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8051C29B14 for ; Thu, 20 Oct 2016 23:55:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7538F29B23; Thu, 20 Oct 2016 23:55:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EA47129B1E for ; Thu, 20 Oct 2016 23:55:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754025AbcJTXzg (ORCPT ); Thu, 20 Oct 2016 19:55:36 -0400 Received: from mga04.intel.com ([192.55.52.120]:37736 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753147AbcJTXzb (ORCPT ); Thu, 20 Oct 2016 19:55:31 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga104.fm.intel.com with ESMTP; 20 Oct 2016 16:55:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,521,1473145200"; d="scan'208";a="1056884017" Received: from mjmartin-nuc01.wa.intel.com ([10.232.97.135]) by fmsmga001.fm.intel.com with ESMTP; 20 Oct 2016 16:55:29 -0700 From: Mat Martineau To: keyrings@vger.kernel.org, linux-security-module@vger.kernel.org, dhowells@redhat.com Cc: Mat Martineau , zohar@linux.vnet.ibm.com Subject: [PATCH v8 09/11] KEYS: Restrict key linkage using a specific keychain Date: Thu, 20 Oct 2016 16:55:21 -0700 Message-Id: <20161020235523.11703-10-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161020235523.11703-1-mathew.j.martineau@linux.intel.com> References: <20161020235523.11703-1-mathew.j.martineau@linux.intel.com> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Adds restrict_link_by_signature_keyring(), which uses the restrict_key member of the provided destination_keyring data structure as the key or keyring to search for signing keys. Signed-off-by: Mat Martineau --- Documentation/crypto/asymmetric-keys.txt | 11 +++++ crypto/asymmetric_keys/asymmetric_type.c | 23 ++++++++++ crypto/asymmetric_keys/restrict.c | 72 ++++++++++++++++++++++++++++++++ include/crypto/public_key.h | 5 +++ 4 files changed, 111 insertions(+) diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt index 07efce6..4cffb60 100644 --- a/Documentation/crypto/asymmetric-keys.txt +++ b/Documentation/crypto/asymmetric-keys.txt @@ -356,6 +356,17 @@ Several restriction methods are available: signing key. The ca_keys kernel parameter also affects which keys are used for signature verification. + (3) Restrict using a separate key or keyring + + - Options used when creating the keyring: + - restrict=asymmetric:key_or_keyring: + + Whenever a key link is requested, the link will only succeed if the key + being linked is signed by one of the designated keys. This key may be + specified directly by providing a serial number for one asymmetric key, or + a group of keys may be searched for the signing key by providing the + serial number for a keyring. + In all of these cases, if the signing key is found the signature of the key to be linked will be verified using the signing key. The requested key is added to the keyring only if the signature is successfully verified. -ENOKEY is diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 8039a69..cd6c217 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -513,6 +513,11 @@ static struct key_restriction *asymmetric_restriction_alloc( return keyres; } +static void asymmetric_free_key_data(void *data) +{ + key_put((struct key *)data); +} + /* * look up keyring restrict functions for asymmetric keys */ @@ -529,6 +534,24 @@ static struct key_restriction *asymmetric_lookup_restrict(char *restriction) restrict_link_by_builtin_and_secondary_trusted, NULL, NULL); + restrict_method = strsep(&restriction, ":"); + + if ((strcmp(restrict_method, "key_or_keyring") == 0) && restriction) { + key_serial_t serial; + struct key *key; + + if (kstrtos32(restriction, 0, &serial) < 0) + return ERR_PTR(-EINVAL); + + key = key_lookup(serial); + if (IS_ERR(key)) + return ERR_PTR(-EINVAL); + + return asymmetric_restriction_alloc(restrict_link_by_key_or_keyring, + asymmetric_free_key_data, + key); + } + return ERR_PTR(-EINVAL); } diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index d223929..b61002b 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -109,3 +109,75 @@ int restrict_link_by_signature(struct key *dest_keyring, key_put(key); return ret; } + +/** + * restrict_link_by_key_or_keyring - Restrict additions to a ring of public + * keys using the restrict_key information stored in the ring. + * @dest_keyring: Keyring being linked to. + * @type: The type of key being added. + * @payload: The payload of the new key. + * @data: A key or ring of keys that can be used to vouch for the new cert. + * + * Check the new certificate only against the key or keys passed in the data + * parameter. If one of those is the signing key and validates the new + * certificate, then mark the new certificate as being ok to link. + * + * Returns 0 if the new certificate was accepted, -ENOKEY if we + * couldn't find a matching parent certificate in the trusted list, + * -EKEYREJECTED if the signature check fails, and some other error if + * there is a matching certificate but the signature check cannot be + * performed. + */ +int restrict_link_by_key_or_keyring(struct key *dest_keyring, + const struct key_type *type, + const union key_payload *payload, + void *data) +{ + const struct public_key_signature *sig; + struct key *key; + int ret; + struct key *trusted = (struct key *) data; + + pr_devel("==>%s()\n", __func__); + + if (!dest_keyring) + return -ENOKEY; + else if (dest_keyring->type != &key_type_keyring) + return -EOPNOTSUPP; + + if (!trusted) + return -ENOKEY; + + if (type != &key_type_asymmetric) + return -EOPNOTSUPP; + + sig = payload->data[asym_auth]; + if (!sig->auth_ids[0] && !sig->auth_ids[1]) + return -ENOKEY; + + if (trusted->type == &key_type_keyring) { + /* See if we have a key that signed this one. */ + key = find_asymmetric_key(trusted, sig->auth_ids[0], + sig->auth_ids[1], false); + if (IS_ERR(key)) + return -ENOKEY; + } else if (trusted->type == &key_type_asymmetric) { + const struct asymmetric_key_ids *kids; + + kids = asymmetric_key_ids(trusted); + + if (!asymmetric_key_id_same(kids->id[1], sig->auth_ids[0])) + return -ENOKEY; + + key = __key_get(trusted); + } else { + return -EOPNOTSUPP; + } + + ret = key_validate(key); + if (ret == 0) + ret = verify_signature(key, sig); + + key_put(key); + return ret; +} diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 4d71666..8557104 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -59,6 +59,11 @@ extern int restrict_link_by_signature(struct key *trust_keyring, const union key_payload *payload, void *data); +extern int restrict_link_by_key_or_keyring(struct key *trust_keyring, + const struct key_type *type, + const union key_payload *payload, + void *data); + extern int query_asymmetric_key(const struct kernel_pkey_params *, struct kernel_pkey_query *);