Skip to content

Commit 952035b

Browse files
ambarusherbertx
authored andcommitted
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 <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 0876d16 commit 952035b

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

crypto/ecdh.c

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ struct ecdh_ctx {
2020
unsigned int curve_id;
2121
unsigned int ndigits;
2222
u64 private_key[ECC_MAX_DIGITS];
23-
u64 public_key[2 * ECC_MAX_DIGITS];
24-
u64 shared_secret[ECC_MAX_DIGITS];
2523
};
2624

2725
static 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,
7068

7169
static int ecdh_compute_value(struct kpp_request *req)
7270
{
73-
int ret = 0;
7471
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
7572
struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
76-
size_t copied, nbytes;
73+
u64 *public_key;
74+
u64 *shared_secret = NULL;
7775
void *buf;
76+
size_t copied, nbytes, public_key_sz;
77+
int ret = -ENOMEM;
7878

7979
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;
8086

8187
if (req->src) {
82-
copied = sg_copy_to_buffer(req->src, 1, ctx->public_key,
83-
2 * nbytes);
84-
if (copied != 2 * nbytes)
85-
return -EINVAL;
88+
shared_secret = kmalloc(nbytes, GFP_KERNEL);
89+
if (!shared_secret)
90+
goto free_pubkey;
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+
}
8698

8799
ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
88-
ctx->private_key,
89-
ctx->public_key,
90-
ctx->shared_secret);
100+
ctx->private_key, public_key,
101+
shared_secret);
91102

92-
buf = ctx->shared_secret;
103+
buf = shared_secret;
93104
} else {
94105
ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits,
95-
ctx->private_key, ctx->public_key);
96-
buf = ctx->public_key;
97-
/* Public part is a point thus it has both coordinates */
98-
nbytes *= 2;
106+
ctx->private_key, public_key);
107+
buf = public_key;
108+
nbytes = public_key_sz;
99109
}
100110

101111
if (ret < 0)
102-
return ret;
112+
goto free_all;
103113

104114
copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes);
105115
if (copied != nbytes)
106-
return -EINVAL;
116+
ret = -EINVAL;
107117

118+
/* fall through */
119+
free_all:
120+
kzfree(shared_secret);
121+
free_pubkey:
122+
kfree(public_key);
108123
return ret;
109124
}
110125

0 commit comments

Comments
 (0)