From: David Howells Subject: [PATCH 10/14] KEYS: Add a crypto key request function Date: Mon, 28 Nov 2011 15:46:30 +0000 Message-ID: <20111128154630.6009.70895.stgit@warthog.procyon.org.uk> References: <20111128154436.6009.77586.stgit@warthog.procyon.org.uk> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Cc: linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, mitry.kasatkin@intel.com, zohar@linux.vnet.ibm.com, arjan.van.de.ven@intel.com, alan.cox@intel.com, David Howells To: keyrings@linux-nfs.org Return-path: In-Reply-To: <20111128154436.6009.77586.stgit@warthog.procyon.org.uk> Sender: linux-kernel-owner@vger.kernel.org List-Id: linux-crypto.vger.kernel.org Add a function by which crypto keys can be requested. A keyring is supplied for the function to search (which can be, say, a system keyring containing keys for kernel module signature checking). The function also provides a point at which hardware key caches, such as a TPM, can be consulted. Signed-off-by: David Howells --- Documentation/security/keys-crypto.txt | 12 ++++ include/keys/crypto-type.h | 3 + security/keys/Makefile | 2 - security/keys/crypto_request.c | 94 ++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletions(-) create mode 100644 security/keys/crypto_request.c diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt index 236d750c..e1c19ea 100644 --- a/Documentation/security/keys-crypto.txt +++ b/Documentation/security/keys-crypto.txt @@ -158,6 +158,18 @@ using a key to provide the public key: not necessary if verify_sig_end() was called. +To find a key to use for signature verification, the following function may be +called: + + struct key *request_crypto_key_for_PGP_sig(struct key *keyring, + const u8 *sig, size_t siglen); + +This parses the specified signature blob to find the signing key identity and +then searches the given keyring for a matching key. It may also examine a +hardware keystore (such as a TPM) for a usable signature matching service and +generate a key to provide an access method to that service. + + ============================ IMPLEMENTING CRYPTO SUBTYPES ============================ diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h index 6b93366..142611b 100644 --- a/include/keys/crypto-type.h +++ b/include/keys/crypto-type.h @@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_key_verify_context *ctx); * The payload is at the discretion of the subtype. */ +extern struct key *request_crypto_key_for_PGP_sig(struct key *keyring, + const u8 *sig, size_t siglen); + #endif /* _KEYS_CRYPTO_TYPE_H */ diff --git a/security/keys/Makefile b/security/keys/Makefile index d6b691b..63def08 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -22,5 +22,5 @@ obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o -crypto_keys-y := crypto_type.o pgp_parse.o crypto_verify.o +crypto_keys-y := crypto_type.o pgp_parse.o crypto_verify.o crypto_request.o crypto_dsa-y := crypto_dsa_subtype.o crypto_dsa_verify.o diff --git a/security/keys/crypto_request.c b/security/keys/crypto_request.c new file mode 100644 index 0000000..98e4a17 --- /dev/null +++ b/security/keys/crypto_request.c @@ -0,0 +1,94 @@ +/* Cryptographic key request handling + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + * + * See Documentation/security/keys-crypto.txt + */ + +#define __KDEBUG +#include +#include +#include +#include +#include +#include "crypto_keys.h" +#include "internal.h" + +struct PGP_sig_parse_context { + struct pgp_parse_context pgp; + struct pgp_sig_parameters params; + bool found_sig; +}; + +/* + * Look inside signature sections for a key ID + */ +static int PGP_sig_parse_signature(struct pgp_parse_context *context, + enum pgp_packet_tag type, + u8 headerlen, + const u8 *data, + size_t datalen) +{ + struct PGP_sig_parse_context *ctx = + container_of(context, struct PGP_sig_parse_context, pgp); + + ctx->found_sig = true; + return pgp_parse_sig_params(&data, &datalen, &ctx->params); +} + +/** + * request_crypto_key_for_PGP_sig - Request a key matching a PGP signature + * @keyring: The keyring that might contain the key. + * @sig: The PGP signature blob. + * @siglen: The size of the PGP signature blob. + * + * Attempt to find a key to use for PGP signature verification, starting off by + * looking in the supplied keyring. The function may also look for other key + * sources such as a TPM. If an alternative key is found it will be added to + * the keyring for future reference. + */ +struct key *request_crypto_key_for_PGP_sig(struct key *keyring, + const u8 *sig, size_t siglen) +{ + struct PGP_sig_parse_context p; + key_ref_t key; + char criterion[3 + 8 * 2 + 1]; + int ret; + + kenter(""); + + if (!keyring) + return ERR_PTR(-ENOKEY); + + /* Need to find the key ID */ + p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE); + p.pgp.process_packet = PGP_sig_parse_signature; + p.found_sig = false; + ret = pgp_parse_packets(sig, siglen, &p.pgp); + if (ret < 0) + return ERR_PTR(ret); + + if (!p.found_sig) + return ERR_PTR(-EINVAL); + + sprintf(criterion, "id:%08x%08x", + be32_to_cpu(p.params.issuer32[0]), + be32_to_cpu(p.params.issuer32[1])); + + kdebug("Look up: %s", criterion); + + key = keyring_search(make_key_ref(keyring, 1), + &key_type_crypto, criterion); + if (IS_ERR(key)) { + kleave(" = %ld", PTR_ERR(key)); + return ERR_CAST(key); + } + + return key_ref_to_ptr(key); +}