Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id

From: Mat Martineau
Date: Wed Jun 29 2016 - 14:43:26 EST



Tadeusz,

On Thu, 23 Jun 2016, Tadeusz Struk wrote:

This patch adds support for asymmetric key type to AF_ALG.
It will work as follows: A new PF_ALG socket options are
added on top of existing ALG_SET_KEY and ALG_SET_PUBKEY, namely
ALG_SET_KEY_ID and ALG_SET_PUBKEY_ID for setting public and
private keys respectively. When these new options will be used
the user, instead of providing the key material, will provide a
key id and the key itself will be obtained from kernel keyring
subsystem. The user will use the standard tools (keyctl tool
or the keyctl syscall) for key instantiation and to obtain the
key id. The key id can also be obtained by reading the
/proc/keys file.

When a key corresponding to the given keyid is found, it is stored
in the socket context and subsequent crypto operation invoked by the
user will use the new asymmetric accessor functions instead of akcipher
api. The asymmetric subtype can internally use akcipher api or
invoke operations defined by a given subtype, depending on the
key type.

Signed-off-by: Tadeusz Struk <tadeusz.struk@xxxxxxxxx>
---
crypto/af_alg.c | 10 ++
crypto/algif_akcipher.c | 212 ++++++++++++++++++++++++++++++++++++++++++-
include/crypto/if_alg.h | 1
include/uapi/linux/if_alg.h | 2
4 files changed, 220 insertions(+), 5 deletions(-)

diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
index 2b8d37e..106f715 100644
--- a/crypto/algif_akcipher.c
+++ b/crypto/algif_akcipher.c
+static int asym_key_verify(const struct key *key, struct akcipher_request *req)
+{
+ struct public_key_signature sig;
+ char *src = NULL, *in, digest[20];
+ int ret;
+
+ if (!sg_is_last(req->src)) {
+ src = kmalloc(req->src_len, GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+ scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
+ in = src;
+ } else {
+ in = sg_virt(req->src);
+ }
+ sig.pkey_algo = "rsa";
+ sig.encoding = "pkcs1";
+ /* Need to find a way to pass the hash param */

Comment still needed?

+ sig.hash_algo = "sha1";
+ sig.digest_size = sizeof(digest);
+ sig.digest = digest;
+ sig.s_size = req->src_len;
+ sig.s = src;
+ ret = verify_signature(key, &sig);
+ if (!ret) {
+ req->dst_len = sizeof(digest);

I think you fixed the BUG_ON() problem but there's still an issue with the handling of the digest. Check the use of sig->digest in public_key_verify_signature(), it's an input not an output. Right now it looks like 20 uninitialized bytes are compared with the computed digest within verify_signature, and then the unintialized bytes are copied to req->dst here.

With some modifications to public_key_verify_signature you could get the digest you need, but I'm not sure if verification with a hardware key (like a key in a TPM) can or can not provide the digest needed. Maybe this is why the verify_signature hook in struct asymmetric_key_subtype is optional.

+ scatterwalk_map_and_copy(digest, req->dst, 0, req->dst_len, 1);
+ }
+ kfree(src);
+ return ret;
+}
+

--
Mat Martineau
Intel OTC