summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2018-03-02 01:37:42 +0300
committerHerbert Xu <herbert@gondor.apana.org.au>2018-03-09 17:45:49 +0300
commit95ec01ba1ef01ffe3cfa755d3d61e24c863ed9b2 (patch)
tree6ab28e34b5c256b7db5bf44e5b478f758dee3829
parenta7d85e06ed8033f263451f3aef4159024e7dae5f (diff)
downloadlinux-95ec01ba1ef01ffe3cfa755d3d61e24c863ed9b2.tar.xz
crypto: ecdh - fix to allow multi segment scatterlists
Apparently the ecdh use case was in bluetooth which always has single element scatterlists, so the ecdh module was hard coded to expect them. Now we're using this in TPM, we need multi-element scatterlists, so remove this limitation. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/ecdh.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index 3aca0933ec44..d2ec33f0e098 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -89,12 +89,19 @@ static int ecdh_compute_value(struct kpp_request *req)
if (!shared_secret)
goto free_pubkey;
- copied = sg_copy_to_buffer(req->src, 1, public_key,
- public_key_sz);
- if (copied != public_key_sz) {
- ret = -EINVAL;
+ /* from here on it's invalid parameters */
+ ret = -EINVAL;
+
+ /* must have exactly two points to be on the curve */
+ if (public_key_sz != req->src_len)
+ goto free_all;
+
+ copied = sg_copy_to_buffer(req->src,
+ sg_nents_for_len(req->src,
+ public_key_sz),
+ public_key, public_key_sz);
+ if (copied != public_key_sz)
goto free_all;
- }
ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
ctx->private_key, public_key,
@@ -111,7 +118,11 @@ static int ecdh_compute_value(struct kpp_request *req)
if (ret < 0)
goto free_all;
- copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes);
+ /* might want less than we've got */
+ nbytes = min_t(size_t, nbytes, req->dst_len);
+ copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst,
+ nbytes),
+ buf, nbytes);
if (copied != nbytes)
ret = -EINVAL;