aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2017-06-08 09:48:10 -0400
committerJames Morris <james.l.morris@oracle.com>2017-06-08 23:29:46 -0400
commite9ff56ac352446f55141aaef1553cee662b2e310 (patch)
tree73e26cc1d669007442c1fb4c22eec12da2ac77aa
parentd636bd9f12a66ea3775c9fabbf3f8e118253467a (diff)
KEYS: encrypted: avoid encrypting/decrypting stack buffers
Since v4.9, the crypto API cannot (normally) be used to encrypt/decrypt stack buffers because the stack may be virtually mapped. Fix this for the padding buffers in encrypted-keys by using ZERO_PAGE for the encryption padding and by allocating a temporary heap buffer for the decryption padding. Tested with CONFIG_DEBUG_SG=y: keyctl new_session keyctl add user master "abcdefghijklmnop" @s keyid=$(keyctl add encrypted desc "new user:master 25" @s) datablob="$(keyctl pipe $keyid)" keyctl unlink $keyid keyid=$(keyctl add encrypted desc "load $datablob" @s) datablob2="$(keyctl pipe $keyid)" [ "$datablob" = "$datablob2" ] && echo "Success!" Cc: Andy Lutomirski <luto@kernel.org> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Mimi Zohar <zohar@linux.vnet.ibm.com> Cc: stable@vger.kernel.org # 4.9+ Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r--security/keys/encrypted-keys/encrypted.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 2ab48eab29a1..d14f1a47a130 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -479,12 +479,9 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
479 struct skcipher_request *req; 479 struct skcipher_request *req;
480 unsigned int encrypted_datalen; 480 unsigned int encrypted_datalen;
481 u8 iv[AES_BLOCK_SIZE]; 481 u8 iv[AES_BLOCK_SIZE];
482 unsigned int padlen;
483 char pad[16];
484 int ret; 482 int ret;
485 483
486 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); 484 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
487 padlen = encrypted_datalen - epayload->decrypted_datalen;
488 485
489 req = init_skcipher_req(derived_key, derived_keylen); 486 req = init_skcipher_req(derived_key, derived_keylen);
490 ret = PTR_ERR(req); 487 ret = PTR_ERR(req);
@@ -492,11 +489,10 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
492 goto out; 489 goto out;
493 dump_decrypted_data(epayload); 490 dump_decrypted_data(epayload);
494 491
495 memset(pad, 0, sizeof pad);
496 sg_init_table(sg_in, 2); 492 sg_init_table(sg_in, 2);
497 sg_set_buf(&sg_in[0], epayload->decrypted_data, 493 sg_set_buf(&sg_in[0], epayload->decrypted_data,
498 epayload->decrypted_datalen); 494 epayload->decrypted_datalen);
499 sg_set_buf(&sg_in[1], pad, padlen); 495 sg_set_page(&sg_in[1], ZERO_PAGE(0), AES_BLOCK_SIZE, 0);
500 496
501 sg_init_table(sg_out, 1); 497 sg_init_table(sg_out, 1);
502 sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen); 498 sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
@@ -583,9 +579,14 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
583 struct skcipher_request *req; 579 struct skcipher_request *req;
584 unsigned int encrypted_datalen; 580 unsigned int encrypted_datalen;
585 u8 iv[AES_BLOCK_SIZE]; 581 u8 iv[AES_BLOCK_SIZE];
586 char pad[16]; 582 u8 *pad;
587 int ret; 583 int ret;
588 584
585 /* Throwaway buffer to hold the unused zero padding at the end */
586 pad = kmalloc(AES_BLOCK_SIZE, GFP_KERNEL);
587 if (!pad)
588 return -ENOMEM;
589
589 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); 590 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
590 req = init_skcipher_req(derived_key, derived_keylen); 591 req = init_skcipher_req(derived_key, derived_keylen);
591 ret = PTR_ERR(req); 592 ret = PTR_ERR(req);
@@ -593,13 +594,12 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
593 goto out; 594 goto out;
594 dump_encrypted_data(epayload, encrypted_datalen); 595 dump_encrypted_data(epayload, encrypted_datalen);
595 596
596 memset(pad, 0, sizeof pad);
597 sg_init_table(sg_in, 1); 597 sg_init_table(sg_in, 1);
598 sg_init_table(sg_out, 2); 598 sg_init_table(sg_out, 2);
599 sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen); 599 sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen);
600 sg_set_buf(&sg_out[0], epayload->decrypted_data, 600 sg_set_buf(&sg_out[0], epayload->decrypted_data,
601 epayload->decrypted_datalen); 601 epayload->decrypted_datalen);
602 sg_set_buf(&sg_out[1], pad, sizeof pad); 602 sg_set_buf(&sg_out[1], pad, AES_BLOCK_SIZE);
603 603
604 memcpy(iv, epayload->iv, sizeof(iv)); 604 memcpy(iv, epayload->iv, sizeof(iv));
605 skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv); 605 skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv);
@@ -611,6 +611,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
611 goto out; 611 goto out;
612 dump_decrypted_data(epayload); 612 dump_decrypted_data(epayload);
613out: 613out:
614 kfree(pad);
614 return ret; 615 return ret;
615} 616}
616 617