diff options
author | Eric Biggers | 2017-06-08 08:48:10 -0500 |
---|---|---|
committer | James Morris | 2017-06-08 22:29:46 -0500 |
commit | e9ff56ac352446f55141aaef1553cee662b2e310 (patch) | |
tree | 73e26cc1d669007442c1fb4c22eec12da2ac77aa | |
parent | d636bd9f12a66ea3775c9fabbf3f8e118253467a (diff) | |
download | linux-phy-e9ff56ac352446f55141aaef1553cee662b2e310.tar.gz linux-phy-e9ff56ac352446f55141aaef1553cee662b2e310.tar.xz linux-phy-e9ff56ac352446f55141aaef1553cee662b2e310.zip |
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.c | 17 |
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); |
613 | out: | 613 | out: |
614 | kfree(pad); | ||
614 | return ret; | 615 | return ret; |
615 | } | 616 | } |
616 | 617 | ||