summaryrefslogtreecommitdiffstatshomepage
path: root/crypto/ecdh.c
diff options
context:
space:
mode:
authorTudor-Dan Ambarus <tudor.ambarus@microchip.com>2017-07-19 23:37:39 -0800
committerHerbert Xu <herbert@gondor.apana.org.au>2017-08-02 21:47:22 -0800
commit952035baedb15d956d5f25b34287d728c751cac9 (patch)
tree4b45b62c2ff36007e7b7e208893fa0fcb16fa88e /crypto/ecdh.c
parent0876d16124d41b78f7fdbd96ad42b1d7b13fe620 (diff)
downloadlinux-stable-952035baedb15d956d5f25b34287d728c751cac9.tar.gz
linux-stable-952035baedb15d956d5f25b34287d728c751cac9.tar.bz2
linux-stable-952035baedb15d956d5f25b34287d728c751cac9.tar.xz
linux-stable-952035baedb15d956d5f25b34287d728c751cac9.zip
crypto: ecdh - fix concurrency on shared secret and pubkey
ecdh_ctx contained static allocated data for the shared secret and public key. The shared secret and the public key were doomed to concurrency issues because they could be shared by multiple crypto requests. The concurrency is fixed by replacing per-tfm shared secret and public key with per-request dynamically allocated shared secret and public key. Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/ecdh.c')
-rw-r--r--crypto/ecdh.c51
1 files changed, 33 insertions, 18 deletions
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index 61c7708905d0..4271fc77d261 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -20,8 +20,6 @@ struct ecdh_ctx {
20 unsigned int curve_id; 20 unsigned int curve_id;
21 unsigned int ndigits; 21 unsigned int ndigits;
22 u64 private_key[ECC_MAX_DIGITS]; 22 u64 private_key[ECC_MAX_DIGITS];
23 u64 public_key[2 * ECC_MAX_DIGITS];
24 u64 shared_secret[ECC_MAX_DIGITS];
25}; 23};
26 24
27static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm) 25static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm)
@@ -70,41 +68,58 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
70 68
71static int ecdh_compute_value(struct kpp_request *req) 69static int ecdh_compute_value(struct kpp_request *req)
72{ 70{
73 int ret = 0;
74 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 71 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
75 struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); 72 struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
76 size_t copied, nbytes; 73 u64 *public_key;
74 u64 *shared_secret = NULL;
77 void *buf; 75 void *buf;
76 size_t copied, nbytes, public_key_sz;
77 int ret = -ENOMEM;
78 78
79 nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT; 79 nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
80 /* Public part is a point thus it has both coordinates */
81 public_key_sz = 2 * nbytes;
82
83 public_key = kmalloc(public_key_sz, GFP_KERNEL);
84 if (!public_key)
85 return -ENOMEM;
80 86
81 if (req->src) { 87 if (req->src) {
82 copied = sg_copy_to_buffer(req->src, 1, ctx->public_key, 88 shared_secret = kmalloc(nbytes, GFP_KERNEL);
83 2 * nbytes); 89 if (!shared_secret)
84 if (copied != 2 * nbytes) 90 goto free_pubkey;
85 return -EINVAL; 91
92 copied = sg_copy_to_buffer(req->src, 1, public_key,
93 public_key_sz);
94 if (copied != public_key_sz) {
95 ret = -EINVAL;
96 goto free_all;
97 }
86 98
87 ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits, 99 ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
88 ctx->private_key, 100 ctx->private_key, public_key,
89 ctx->public_key, 101 shared_secret);
90 ctx->shared_secret);
91 102
92 buf = ctx->shared_secret; 103 buf = shared_secret;
93 } else { 104 } else {
94 ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits, 105 ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits,
95 ctx->private_key, ctx->public_key); 106 ctx->private_key, public_key);
96 buf = ctx->public_key; 107 buf = public_key;
97 /* Public part is a point thus it has both coordinates */ 108 nbytes = public_key_sz;
98 nbytes *= 2;
99 } 109 }
100 110
101 if (ret < 0) 111 if (ret < 0)
102 return ret; 112 goto free_all;
103 113
104 copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes); 114 copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes);
105 if (copied != nbytes) 115 if (copied != nbytes)
106 return -EINVAL; 116 ret = -EINVAL;
107 117
118 /* fall through */
119free_all:
120 kzfree(shared_secret);
121free_pubkey:
122 kfree(public_key);
108 return ret; 123 return ret;
109} 124}
110 125