summaryrefslogtreecommitdiffstats
path: root/security/keys/dh.c
diff options
context:
space:
mode:
authorMat Martineau <mathew.j.martineau@linux.intel.com>2017-06-08 09:50:11 -0400
committerJames Morris <james.l.morris@oracle.com>2017-06-08 23:29:50 -0400
commit7cbe0932c2f2014d6e24e716e79ea3910b468950 (patch)
tree437ceb7be54a31c89b5bebf24b2dcda09210c2a0 /security/keys/dh.c
parentda7798a7b6714cf35ea6084ad6b1fe0497566cf2 (diff)
KEYS: Convert KEYCTL_DH_COMPUTE to use the crypto KPP API
The initial Diffie-Hellman computation made direct use of the MPI library because the crypto module did not support DH at the time. Now that KPP is implemented, KEYCTL_DH_COMPUTE should use it to get rid of duplicate code and leverage possible hardware acceleration. This fixes an issue whereby the input to the KDF computation would include additional uninitialized memory when the result of the Diffie-Hellman computation was shorter than the input prime number. Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <james.l.morris@oracle.com>
Diffstat (limited to 'security/keys/dh.c')
-rw-r--r--security/keys/dh.c272
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/* 21static 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 */
33static int do_dh(MPI result, MPI base, MPI xa, MPI p)
34{
35 return mpi_powm(result, base, xa, p);
36}
37
38static 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
63static void dh_free_data(struct dh *dh)
64{
65 kzfree(dh->key);
66 kzfree(dh->p);
67 kzfree(dh->g);
68}
69
70struct dh_completion {
71 struct completion completion;
72 int err;
73};
74
75static 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
82struct kdf_sdesc { 86struct 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 */
142static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, 146static 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
193static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, 213static 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
334error5: 402out6:
335 kzfree(kbuf); 403 kpp_request_free(req);
336error4: 404out5:
337 mpi_free(result); 405 kzfree(outbuf);
338error3: 406out4:
339 mpi_free(private); 407 crypto_free_kpp(tfm);
340error2: 408out3:
341 mpi_free(base); 409 kzfree(secret);
342error1: 410out2:
343 mpi_free(prime); 411 dh_free_data(&dh_inputs);
344out: 412out1:
345 kdf_dealloc(sdesc); 413 kdf_dealloc(sdesc);
346 return ret; 414 return ret;
347} 415}