Current implementation of dm-crypt supports block ciphers of the form "template(cipher)", e.g. "cbc(aes)". It does not support stream ciphers of the form "cipher", e.g. "salsa20", that uses the blkcipher interface directly. This patch adds support for stream ciphers using the blkcipher interface directly. It uses a special chainmode called "stream". Example of usage: cryptsetup luksFormat -c salsa20-stream-plain /dev/loop0 Due to the way ESSIV uses the cipher interface directly, it is not possible to use something like "salsa20-stream-essiv:md5". However this is probably not an issue since ESSIV was created to prevent watermarking attacks and for stream ciphers it is always possible, i.e. flip the bits in the plaintext and the ciphertext will flip accordingly. In other words, plain IV generation should be sufficient. WARNING: Using stream ciphers with dm-crypt must be exercised with care. If used on a read-write filesystem, it is trivial to extract the keystream by over-writing files with 0x00s and thus recovering the original plaintext of the overwritten files. Stream ciphers are probably more useful for encrypting large amount of data on read-only filesystem (e.g. media files on DVD-ROMs). Signed-off-by: Tan Swee Heng <thesweeheng@xxxxxxxxx>
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 28c6ae0..7e07b71 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -782,10 +782,19 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad_cipher; } - if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", - chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) { - ti->error = "Chain mode + cipher name is too long"; - goto bad_cipher; + if (strcmp(chainmode, "stream") != 0) { + if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", + chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) { + ti->error = "Chain mode + cipher name is too long"; + goto bad_cipher; + } + } else { + if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s", + cipher) >= CRYPTO_MAX_ALG_NAME) { + ti->error = "Stream cipher name is too long"; + goto bad_cipher; + } + } tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);