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>

authored by Mat Martineau and committed by James Morris 7cbe0932 da7798a7

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