diff options
Diffstat (limited to 'security/keys/dh.c')
-rw-r--r-- | security/keys/dh.c | 272 |
1 files changed, 170 insertions, 102 deletions
diff --git a/security/keys/dh.c b/security/keys/dh.c index 63ac87d430db..4755d4b4f945 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c | |||
@@ -8,34 +8,17 @@ | |||
8 | * 2 of the License, or (at your option) any later version. | 8 | * 2 of the License, or (at your option) any later version. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/mpi.h> | ||
12 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
13 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
13 | #include <linux/scatterlist.h> | ||
14 | #include <linux/crypto.h> | 14 | #include <linux/crypto.h> |
15 | #include <crypto/hash.h> | 15 | #include <crypto/hash.h> |
16 | #include <crypto/kpp.h> | ||
17 | #include <crypto/dh.h> | ||
16 | #include <keys/user-type.h> | 18 | #include <keys/user-type.h> |
17 | #include "internal.h" | 19 | #include "internal.h" |
18 | 20 | ||
19 | /* | 21 | static ssize_t dh_data_from_key(key_serial_t keyid, void **data) |
20 | * Public key or shared secret generation function [RFC2631 sec 2.1.1] | ||
21 | * | ||
22 | * ya = g^xa mod p; | ||
23 | * or | ||
24 | * ZZ = yb^xa mod p; | ||
25 | * | ||
26 | * where xa is the local private key, ya is the local public key, g is | ||
27 | * the generator, p is the prime, yb is the remote public key, and ZZ | ||
28 | * is the shared secret. | ||
29 | * | ||
30 | * Both are the same calculation, so g or yb are the "base" and ya or | ||
31 | * ZZ are the "result". | ||
32 | */ | ||
33 | static int do_dh(MPI result, MPI base, MPI xa, MPI p) | ||
34 | { | ||
35 | return mpi_powm(result, base, xa, p); | ||
36 | } | ||
37 | |||
38 | static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) | ||
39 | { | 22 | { |
40 | struct key *key; | 23 | struct key *key; |
41 | key_ref_t key_ref; | 24 | key_ref_t key_ref; |
@@ -56,19 +39,17 @@ static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) | |||
56 | status = key_validate(key); | 39 | status = key_validate(key); |
57 | if (status == 0) { | 40 | if (status == 0) { |
58 | const struct user_key_payload *payload; | 41 | const struct user_key_payload *payload; |
42 | uint8_t *duplicate; | ||
59 | 43 | ||
60 | payload = user_key_payload_locked(key); | 44 | payload = user_key_payload_locked(key); |
61 | 45 | ||
62 | if (maxlen == 0) { | 46 | duplicate = kmemdup(payload->data, payload->datalen, |
63 | *mpi = NULL; | 47 | GFP_KERNEL); |
48 | if (duplicate) { | ||
49 | *data = duplicate; | ||
64 | ret = payload->datalen; | 50 | ret = payload->datalen; |
65 | } else if (payload->datalen <= maxlen) { | ||
66 | *mpi = mpi_read_raw_data(payload->data, | ||
67 | payload->datalen); | ||
68 | if (*mpi) | ||
69 | ret = payload->datalen; | ||
70 | } else { | 51 | } else { |
71 | ret = -EINVAL; | 52 | ret = -ENOMEM; |
72 | } | 53 | } |
73 | } | 54 | } |
74 | up_read(&key->sem); | 55 | up_read(&key->sem); |
@@ -79,6 +60,29 @@ error: | |||
79 | return ret; | 60 | return ret; |
80 | } | 61 | } |
81 | 62 | ||
63 | static void dh_free_data(struct dh *dh) | ||
64 | { | ||
65 | kzfree(dh->key); | ||
66 | kzfree(dh->p); | ||
67 | kzfree(dh->g); | ||
68 | } | ||
69 | |||
70 | struct dh_completion { | ||
71 | struct completion completion; | ||
72 | int err; | ||
73 | }; | ||
74 | |||
75 | static void dh_crypto_done(struct crypto_async_request *req, int err) | ||
76 | { | ||
77 | struct dh_completion *compl = req->data; | ||
78 | |||
79 | if (err == -EINPROGRESS) | ||
80 | return; | ||
81 | |||
82 | compl->err = err; | ||
83 | complete(&compl->completion); | ||
84 | } | ||
85 | |||
82 | struct kdf_sdesc { | 86 | struct kdf_sdesc { |
83 | struct shash_desc shash; | 87 | struct shash_desc shash; |
84 | char ctx[]; | 88 | char ctx[]; |
@@ -140,7 +144,7 @@ static void kdf_dealloc(struct kdf_sdesc *sdesc) | |||
140 | * 5.8.1.2). | 144 | * 5.8.1.2). |
141 | */ | 145 | */ |
142 | static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, | 146 | static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, |
143 | u8 *dst, unsigned int dlen) | 147 | u8 *dst, unsigned int dlen, unsigned int zlen) |
144 | { | 148 | { |
145 | struct shash_desc *desc = &sdesc->shash; | 149 | struct shash_desc *desc = &sdesc->shash; |
146 | unsigned int h = crypto_shash_digestsize(desc->tfm); | 150 | unsigned int h = crypto_shash_digestsize(desc->tfm); |
@@ -157,6 +161,22 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, | |||
157 | if (err) | 161 | if (err) |
158 | goto err; | 162 | goto err; |
159 | 163 | ||
164 | if (zlen && h) { | ||
165 | u8 tmpbuffer[h]; | ||
166 | size_t chunk = min_t(size_t, zlen, h); | ||
167 | memset(tmpbuffer, 0, chunk); | ||
168 | |||
169 | do { | ||
170 | err = crypto_shash_update(desc, tmpbuffer, | ||
171 | chunk); | ||
172 | if (err) | ||
173 | goto err; | ||
174 | |||
175 | zlen -= chunk; | ||
176 | chunk = min_t(size_t, zlen, h); | ||
177 | } while (zlen); | ||
178 | } | ||
179 | |||
160 | if (src && slen) { | 180 | if (src && slen) { |
161 | err = crypto_shash_update(desc, src, slen); | 181 | err = crypto_shash_update(desc, src, slen); |
162 | if (err) | 182 | if (err) |
@@ -192,7 +212,7 @@ err: | |||
192 | 212 | ||
193 | static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, | 213 | static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, |
194 | char __user *buffer, size_t buflen, | 214 | char __user *buffer, size_t buflen, |
195 | uint8_t *kbuf, size_t kbuflen) | 215 | uint8_t *kbuf, size_t kbuflen, size_t lzero) |
196 | { | 216 | { |
197 | uint8_t *outbuf = NULL; | 217 | uint8_t *outbuf = NULL; |
198 | int ret; | 218 | int ret; |
@@ -203,7 +223,7 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, | |||
203 | goto err; | 223 | goto err; |
204 | } | 224 | } |
205 | 225 | ||
206 | ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen); | 226 | ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen, lzero); |
207 | if (ret) | 227 | if (ret) |
208 | goto err; | 228 | goto err; |
209 | 229 | ||
@@ -221,21 +241,26 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params, | |||
221 | struct keyctl_kdf_params *kdfcopy) | 241 | struct keyctl_kdf_params *kdfcopy) |
222 | { | 242 | { |
223 | long ret; | 243 | long ret; |
224 | MPI base, private, prime, result; | 244 | ssize_t dlen; |
225 | unsigned nbytes; | 245 | int secretlen; |
246 | int outlen; | ||
226 | struct keyctl_dh_params pcopy; | 247 | struct keyctl_dh_params pcopy; |
227 | uint8_t *kbuf; | 248 | struct dh dh_inputs; |
228 | ssize_t keylen; | 249 | struct scatterlist outsg; |
229 | size_t resultlen; | 250 | struct dh_completion compl; |
251 | struct crypto_kpp *tfm; | ||
252 | struct kpp_request *req; | ||
253 | uint8_t *secret; | ||
254 | uint8_t *outbuf; | ||
230 | struct kdf_sdesc *sdesc = NULL; | 255 | struct kdf_sdesc *sdesc = NULL; |
231 | 256 | ||
232 | if (!params || (!buffer && buflen)) { | 257 | if (!params || (!buffer && buflen)) { |
233 | ret = -EINVAL; | 258 | ret = -EINVAL; |
234 | goto out; | 259 | goto out1; |
235 | } | 260 | } |
236 | if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { | 261 | if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { |
237 | ret = -EFAULT; | 262 | ret = -EFAULT; |
238 | goto out; | 263 | goto out1; |
239 | } | 264 | } |
240 | 265 | ||
241 | if (kdfcopy) { | 266 | if (kdfcopy) { |
@@ -244,104 +269,147 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params, | |||
244 | if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || | 269 | if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || |
245 | kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { | 270 | kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { |
246 | ret = -EMSGSIZE; | 271 | ret = -EMSGSIZE; |
247 | goto out; | 272 | goto out1; |
248 | } | 273 | } |
249 | 274 | ||
250 | /* get KDF name string */ | 275 | /* get KDF name string */ |
251 | hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); | 276 | hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); |
252 | if (IS_ERR(hashname)) { | 277 | if (IS_ERR(hashname)) { |
253 | ret = PTR_ERR(hashname); | 278 | ret = PTR_ERR(hashname); |
254 | goto out; | 279 | goto out1; |
255 | } | 280 | } |
256 | 281 | ||
257 | /* allocate KDF from the kernel crypto API */ | 282 | /* allocate KDF from the kernel crypto API */ |
258 | ret = kdf_alloc(&sdesc, hashname); | 283 | ret = kdf_alloc(&sdesc, hashname); |
259 | kfree(hashname); | 284 | kfree(hashname); |
260 | if (ret) | 285 | if (ret) |
261 | goto out; | 286 | goto out1; |
262 | } | 287 | } |
263 | 288 | ||
264 | /* | 289 | memset(&dh_inputs, 0, sizeof(dh_inputs)); |
265 | * If the caller requests postprocessing with a KDF, allow an | 290 | |
266 | * arbitrary output buffer size since the KDF ensures proper truncation. | 291 | dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p); |
267 | */ | 292 | if (dlen < 0) { |
268 | keylen = mpi_from_key(pcopy.prime, kdfcopy ? SIZE_MAX : buflen, &prime); | 293 | ret = dlen; |
269 | if (keylen < 0 || !prime) { | 294 | goto out1; |
270 | /* buflen == 0 may be used to query the required buffer size, | ||
271 | * which is the prime key length. | ||
272 | */ | ||
273 | ret = keylen; | ||
274 | goto out; | ||
275 | } | 295 | } |
296 | dh_inputs.p_size = dlen; | ||
276 | 297 | ||
277 | /* The result is never longer than the prime */ | 298 | dlen = dh_data_from_key(pcopy.base, &dh_inputs.g); |
278 | resultlen = keylen; | 299 | if (dlen < 0) { |
300 | ret = dlen; | ||
301 | goto out2; | ||
302 | } | ||
303 | dh_inputs.g_size = dlen; | ||
279 | 304 | ||
280 | keylen = mpi_from_key(pcopy.base, SIZE_MAX, &base); | 305 | dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); |
281 | if (keylen < 0 || !base) { | 306 | if (dlen < 0) { |
282 | ret = keylen; | 307 | ret = dlen; |
283 | goto error1; | 308 | goto out2; |
284 | } | 309 | } |
310 | dh_inputs.key_size = dlen; | ||
285 | 311 | ||
286 | keylen = mpi_from_key(pcopy.private, SIZE_MAX, &private); | 312 | secretlen = crypto_dh_key_len(&dh_inputs); |
287 | if (keylen < 0 || !private) { | 313 | secret = kmalloc(secretlen, GFP_KERNEL); |
288 | ret = keylen; | 314 | if (!secret) { |
289 | goto error2; | 315 | ret = -ENOMEM; |
316 | goto out2; | ||
317 | } | ||
318 | ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs); | ||
319 | if (ret) | ||
320 | goto out3; | ||
321 | |||
322 | tfm = crypto_alloc_kpp("dh", CRYPTO_ALG_TYPE_KPP, 0); | ||
323 | if (IS_ERR(tfm)) { | ||
324 | ret = PTR_ERR(tfm); | ||
325 | goto out3; | ||
326 | } | ||
327 | |||
328 | ret = crypto_kpp_set_secret(tfm, secret, secretlen); | ||
329 | if (ret) | ||
330 | goto out4; | ||
331 | |||
332 | outlen = crypto_kpp_maxsize(tfm); | ||
333 | |||
334 | if (!kdfcopy) { | ||
335 | /* | ||
336 | * When not using a KDF, buflen 0 is used to read the | ||
337 | * required buffer length | ||
338 | */ | ||
339 | if (buflen == 0) { | ||
340 | ret = outlen; | ||
341 | goto out4; | ||
342 | } else if (outlen > buflen) { | ||
343 | ret = -EOVERFLOW; | ||
344 | goto out4; | ||
345 | } | ||
290 | } | 346 | } |
291 | 347 | ||
292 | result = mpi_alloc(0); | 348 | outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen, |
293 | if (!result) { | 349 | GFP_KERNEL); |
350 | if (!outbuf) { | ||
294 | ret = -ENOMEM; | 351 | ret = -ENOMEM; |
295 | goto error3; | 352 | goto out4; |
296 | } | 353 | } |
297 | 354 | ||
298 | /* allocate space for DH shared secret and SP800-56A otherinfo */ | 355 | sg_init_one(&outsg, outbuf, outlen); |
299 | kbuf = kmalloc(kdfcopy ? (resultlen + kdfcopy->otherinfolen) : resultlen, | 356 | |
300 | GFP_KERNEL); | 357 | req = kpp_request_alloc(tfm, GFP_KERNEL); |
301 | if (!kbuf) { | 358 | if (!req) { |
302 | ret = -ENOMEM; | 359 | ret = -ENOMEM; |
303 | goto error4; | 360 | goto out5; |
304 | } | 361 | } |
305 | 362 | ||
363 | kpp_request_set_input(req, NULL, 0); | ||
364 | kpp_request_set_output(req, &outsg, outlen); | ||
365 | init_completion(&compl.completion); | ||
366 | kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | | ||
367 | CRYPTO_TFM_REQ_MAY_SLEEP, | ||
368 | dh_crypto_done, &compl); | ||
369 | |||
306 | /* | 370 | /* |
307 | * Concatenate SP800-56A otherinfo past DH shared secret -- the | 371 | * For DH, generate_public_key and generate_shared_secret are |
308 | * input to the KDF is (DH shared secret || otherinfo) | 372 | * the same calculation |
309 | */ | 373 | */ |
310 | if (kdfcopy && | 374 | ret = crypto_kpp_generate_public_key(req); |
311 | copy_from_user(kbuf + resultlen, kdfcopy->otherinfo, | 375 | if (ret == -EINPROGRESS) { |
312 | kdfcopy->otherinfolen) != 0) { | 376 | wait_for_completion(&compl.completion); |
313 | ret = -EFAULT; | 377 | ret = compl.err; |
314 | goto error5; | 378 | if (ret) |
379 | goto out6; | ||
315 | } | 380 | } |
316 | 381 | ||
317 | ret = do_dh(result, base, private, prime); | ||
318 | if (ret) | ||
319 | goto error5; | ||
320 | |||
321 | ret = mpi_read_buffer(result, kbuf, resultlen, &nbytes, NULL); | ||
322 | if (ret != 0) | ||
323 | goto error5; | ||
324 | |||
325 | if (kdfcopy) { | 382 | if (kdfcopy) { |
326 | ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, kbuf, | 383 | /* |
327 | resultlen + kdfcopy->otherinfolen); | 384 | * Concatenate SP800-56A otherinfo past DH shared secret -- the |
328 | } else { | 385 | * input to the KDF is (DH shared secret || otherinfo) |
329 | ret = nbytes; | 386 | */ |
330 | if (copy_to_user(buffer, kbuf, nbytes) != 0) | 387 | if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo, |
388 | kdfcopy->otherinfolen) != 0) { | ||
331 | ret = -EFAULT; | 389 | ret = -EFAULT; |
390 | goto out6; | ||
391 | } | ||
392 | |||
393 | ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, outbuf, | ||
394 | req->dst_len + kdfcopy->otherinfolen, | ||
395 | outlen - req->dst_len); | ||
396 | } else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) { | ||
397 | ret = req->dst_len; | ||
398 | } else { | ||
399 | ret = -EFAULT; | ||
332 | } | 400 | } |
333 | 401 | ||
334 | error5: | 402 | out6: |
335 | kzfree(kbuf); | 403 | kpp_request_free(req); |
336 | error4: | 404 | out5: |
337 | mpi_free(result); | 405 | kzfree(outbuf); |
338 | error3: | 406 | out4: |
339 | mpi_free(private); | 407 | crypto_free_kpp(tfm); |
340 | error2: | 408 | out3: |
341 | mpi_free(base); | 409 | kzfree(secret); |
342 | error1: | 410 | out2: |
343 | mpi_free(prime); | 411 | dh_free_data(&dh_inputs); |
344 | out: | 412 | out1: |
345 | kdf_dealloc(sdesc); | 413 | kdf_dealloc(sdesc); |
346 | return ret; | 414 | return ret; |
347 | } | 415 | } |