trusted-keys: skcipher bug info
Subsystems (4)
PATCH 1/1 trusted-keys: skcipher bug info
Hi Herbert,
The initial random iv value, initialized in encrypted_init(), should not be modified. Commit c3917fd "KEYS: Use skcipher", which replaced the blkcipher with skcipher, modifies the iv in crypto_skcipher_encrypt()/decrypt().
The following example creates an encrypted key, writes the key to a file, and then loads the key from the file. To illustrate the problem, this patch provides crypto_skcipher_encrypt()/decrypt() with a copy of the iv. With this change, the resulting test-key and test-key1 keys are the same.
keyctl add user kmk "dd if=/dev/urandom bs=1 count=32 2>/dev/null" @u keyctl pipe keyctl search @u user kmk > ~/tmp/kmk
keyctl add encrypted test-key "new user:kmk 64" @u
keyctl pipe keyctl search @u encrypted test-key > /tmp/test-key1 keyctl add encrypted test-key1 "load cat /tmp/test-key1" @u
keyctl print keyctl search @u encrypted test-key keyctl print keyctl search @u encrypted test-key1
Either the underlying problem should be fixed or commit c3917fd "KEYS: Use skcipher" should be reverted.
thanks,
Mimi
--- security/keys/encrypted-keys/encrypted.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
security/keys/encrypted-keys/encrypted.c +19 -3
@@ -480,6 +480,7 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,unsigned int encrypted_datalen;unsigned int padlen;char pad[16 ]; +u8 iv[16 ];int ret; encrypted_datalen =roundup (epayload->decrypted_datalen, blksize);
@@ -500,9 +501,19 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,sg_init_table (sg_out,1 );sg_set_buf (sg_out, epayload->encrypted_data, encrypted_datalen); +memcpy (iv, epayload->iv,16 );/* iv is modified */ skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, - epayload->iv); + iv); +print_hex_dump (KERN_INFO ,"original iv: " ,DUMP_PREFIX_NONE ,32 ,1 , + epayload->iv, ivsize,0 ); +print_hex_dump (KERN_INFO ,"copied iv: " ,DUMP_PREFIX_NONE ,32 ,1 , + iv, ivsize,0 ); ret =crypto_skcipher_encrypt (req); +print_hex_dump (KERN_INFO ,"original iv: " ,DUMP_PREFIX_NONE ,32 ,1 , + epayload->iv, ivsize,0 ); +print_hex_dump (KERN_INFO ,"modified iv: " ,DUMP_PREFIX_NONE ,32 ,1 , + iv, ivsize,0 ); + tfm =crypto_skcipher_reqtfm (req);skcipher_request_free (req);crypto_free_skcipher (tfm);
@@ -582,6 +593,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,struct skcipher_request *req;unsigned int encrypted_datalen;char pad[16 ]; +u8 iv[16 ];int ret; encrypted_datalen =roundup (epayload->decrypted_datalen, blksize);
@@ -599,8 +611,9 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, epayload->decrypted_datalen);sg_set_buf (&sg_out[1 ], pad,sizeof pad); +memcpy (iv, epayload->iv,16 );/* iv is modified */ skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, - epayload->iv); + iv); ret =crypto_skcipher_decrypt (req); tfm =crypto_skcipher_reqtfm (req);skcipher_request_free (req);
@@ -778,8 +791,11 @@ static int encrypted_init(struct encrypted_key_payload *epayload,get_random_bytes (epayload->decrypted_data, epayload->decrypted_datalen); - }else + }else { ret =encrypted_key_decrypt (epayload, format, hex_encoded_iv); +print_hex_dump (KERN_INFO ,"init iv: " ,DUMP_PREFIX_NONE ,32 ,1 , + epayload->iv, ivsize,0 ); + }return ret; }
Signature · 1 line
2.7.4
Herbert Xu
maintainerQuoted 7 lines · Mimi Zohar
Hi Herbert,
The initial random iv value, initialized in
encrypted_init(), should not be modified. Commit c3917fd "KEYS: Use skcipher", which replaced the blkcipher with skcipher, modifies the iv in crypto_skcipher_encrypt()/decrypt().
Quoted 5 lines
The following example creates an encrypted key, writes the key to a file, and then loads the key from the file. To illustrate the problem, this patch provides crypto_skcipher_encrypt()/decrypt() with a copy of the iv. With this change, the resulting test-key and test-key1 keys are the same.
Sorry, I missed the subtlety. This patch should fix the problem.
---8<---
Subject: KEYS: Fix skcipher IV clobbering
The IV must not be modified by the skcipher operation so we need to duplicate it.
security/keys/encrypted-keys/encrypted.c +7 -4
@@ -29,6 +29,7 @@#include <linux/rcupdate.h> #include <linux/scatterlist.h> #include <linux/ctype.h> +#include <crypto/aes.h> #include <crypto/hash.h> #include <crypto/sha.h> #include <crypto/skcipher.h>
@@ -478,6 +479,7 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,struct crypto_skcipher *tfm;struct skcipher_request *req;unsigned int encrypted_datalen; +u8 iv[AES_BLOCK_SIZE ];unsigned int padlen;char pad[16 ];int ret;
@@ -500,8 +502,8 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,sg_init_table (sg_out,1 );sg_set_buf (sg_out, epayload->encrypted_data, encrypted_datalen); -skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, - epayload->iv); +memcpy (iv, epayload->iv,sizeof (iv)); +skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, iv); ret =crypto_skcipher_encrypt (req); tfm =crypto_skcipher_reqtfm (req);skcipher_request_free (req);
@@ -581,6 +583,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,struct crypto_skcipher *tfm;struct skcipher_request *req;unsigned int encrypted_datalen; +u8 iv[AES_BLOCK_SIZE ];char pad[16 ];int ret;
@@ -599,8 +602,8 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, epayload->decrypted_datalen);sg_set_buf (&sg_out[1 ], pad,sizeof pad); -skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, - epayload->iv); +memcpy (iv, epayload->iv,sizeof (iv)); +skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, iv); ret =crypto_skcipher_decrypt (req); tfm =crypto_skcipher_reqtfm (req);skcipher_request_free (req);
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Quoted 8 lines · Herbert Xu
Quoted 7 lines · Mimi Zohar
Hi Herbert,
The initial random iv value, initialized in
encrypted_init(), should not be modified. Commit c3917fd "KEYS: Use skcipher", which replaced the blkcipher with skcipher, modifies the iv in crypto_skcipher_encrypt()/decrypt().
Quoted 7 lines
Quoted 5 lines
The following example creates an encrypted key, writes the key to a file, and then loads the key from the file. To illustrate the problem, this patch provides crypto_skcipher_encrypt()/decrypt() with a copy of the iv. With this change, the resulting test-key and test-key1 keys are the same.
Sorry, I missed the subtlety. This patch should fix the problem.
Thanks!
Mimi
Quoted 63 lines
---8<---
Subject: KEYS: Fix skcipher IV clobberingThe IV must not be modified by the skcipher operation so we need to duplicate it.
Fixes c3917fd9dfbc ("KEYS: Use skcipher")Reported-by Mimi Zohar <[email protected]>Signed-off-by Herbert Xu <[email protected]>security/keys/encrypted-keys/encrypted.c +7
-4@@ -29,6 +29,7 @@#include <linux/rcupdate.h> #include <linux/scatterlist.h> #include <linux/ctype.h> +#include <crypto/aes.h> #include <crypto/hash.h> #include <crypto/sha.h> #include <crypto/skcipher.h> @@ -478,6 +479,7 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,struct crypto_skcipher *tfm;struct skcipher_request *req;unsigned int encrypted_datalen; +u8 iv[AES_BLOCK_SIZE ];unsigned int padlen;char pad[16 ];int ret;@@ -500,8 +502,8 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,sg_init_table (sg_out,1 );sg_set_buf (sg_out, epayload->encrypted_data, encrypted_datalen); -skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, - epayload->iv); +memcpy (iv, epayload->iv,sizeof (iv)); +skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, iv); ret =crypto_skcipher_encrypt (req); tfm =crypto_skcipher_reqtfm (req);skcipher_request_free (req);@@ -581,6 +583,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,struct crypto_skcipher *tfm;struct skcipher_request *req;unsigned int encrypted_datalen; +u8 iv[AES_BLOCK_SIZE ];char pad[16 ];int ret;@@ -599,8 +602,8 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, epayload->decrypted_datalen);sg_set_buf (&sg_out[1 ], pad,sizeof pad); -skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, - epayload->iv); +memcpy (iv, epayload->iv,sizeof (iv)); +skcipher_request_set_crypt (req, sg_in, sg_out, encrypted_datalen, iv); ret =crypto_skcipher_decrypt (req); tfm =crypto_skcipher_reqtfm (req);skcipher_request_free (req);