Without the goto: Signed-off-by: Joel Reardon <reardonj@xxxxxxxxxxx> --- fs/ubifs/compress.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++--- fs/ubifs/ubifs.h | 8 +++++- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/fs/ubifs/compress.c b/fs/ubifs/compress.c index b796b8d..61fe584 100644 --- a/fs/ubifs/compress.c +++ b/fs/ubifs/compress.c @@ -27,9 +27,12 @@ * decompression. */ -#include <linux/crypto.h> #include "ubifs.h" +#include <linux/crypto.h> +#include <linux/scatterlist.h> + + /* Fake description object for the "none" compressor */ static struct ubifs_compressor none_compr = { .compr_type = UBIFS_COMPR_NONE, @@ -75,6 +78,53 @@ static struct ubifs_compressor zlib_compr = { struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; /** + * ubifs_aes_crypt - encrypt / decrypt data. + * @str: data to crypt + * @len: length of the data + * @crypto_key: the cryptographic key to use to crypt the data + * @iv: the initialization vector to use + * + * This function applies aes encryption to the data. It is done in counter + * mode, which means that encryption and decryption are the same operation, + * i.e., it XORs the same generated bitstream, so it can be used both for + * encryption / decryption. The operation is done in-place, so str mutates. + * Both crypto_key and iv are valid pointers to a buffer of length + * UBIFS_CRYPTO_KEYSIZE. + */ +int ubifs_aes_crypt(void *str, int len, u8 *crypto_key, u8 *iv) +{ + struct crypto_blkcipher *tfm; + struct blkcipher_desc desc; + struct scatterlist sg; + int err = 0; + + tfm = crypto_alloc_blkcipher(UBIFS_CRYPTO_ALGORITHM, 0, 0); + if (IS_ERR(tfm)) { + ubifs_err("failed to load transform for aes: %ld", + PTR_ERR(tfm)); + return err; + } + + err = crypto_blkcipher_setkey(tfm, crypto_key, UBIFS_CRYPTO_KEYSIZE); + desc.tfm = tfm; + desc.flags = 0; + if (err) { + ubifs_err("crypto_blkcipher_setkey() failed flags=%#x", + crypto_blkcipher_get_flags(tfm)); + return err; + } + + memset(&sg, 0, sizeof(struct scatterlist)); + sg_set_buf(&sg, str, len); + desc.info = iv; + err = crypto_blkcipher_encrypt(&desc, &sg, &sg, len); + crypto_free_blkcipher(tfm); + if (err) + return err; + return 0; +} + +/** * ubifs_compress - compress data. * @in_buf: data to compress * @in_len: length of the data to compress @@ -126,13 +176,20 @@ void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, */ if (in_len - *out_len < UBIFS_MIN_COMPRESS_DIFF) goto no_compr; - - return; + goto encrypt; no_compr: memcpy(out_buf, in_buf, in_len); *out_len = in_len; *compr_type = UBIFS_COMPR_NONE; + +encrypt: + if (crypto_key) { + u8 iv[UBIFS_CRYPTO_KEYSIZE]; + + memset(iv, 0, UBIFS_CRYPTO_KEYSIZE); + ubifs_aes_crypt(out_buf, *out_len, crypto_key, iv); + } } /** @@ -148,8 +205,10 @@ no_compr: * This function decompresses data from buffer @in_buf into buffer @out_buf. * The length of the uncompressed data is returned in @out_len. This functions * returns %0 on success or a negative error code on failure. + * + * WARNING: this function may modify the contents of in_buf when executing. */ -int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, +int ubifs_decompress(void *in_buf, int in_len, void *out_buf, int *out_len, int compr_type, u8 *crypto_key) { int err; @@ -167,6 +226,13 @@ int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, return -EINVAL; } + if (crypto_key) { + u8 iv[UBIFS_CRYPTO_KEYSIZE]; + + memset(iv, 0, UBIFS_CRYPTO_KEYSIZE); + ubifs_aes_crypt(in_buf, in_len, crypto_key, iv); + } + if (compr_type == UBIFS_COMPR_NONE) { memcpy(out_buf, in_buf, in_len); *out_len = in_len; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 3ed12be..84d2c49 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -160,6 +160,11 @@ /* Maximum number of data nodes to bulk-read */ #define UBIFS_MAX_BULK_READ 32 +/* 128 bit key size in bytes for UBIFS */ +#define UBIFS_CRYPTO_KEYSIZE 16 +/* AES in counter mode is the encryption algorithm. */ +#define UBIFS_CRYPTO_ALGORITHM "ctr(aes)" + /* * Lockdep classes for UBIFS inode @ui_mutex. */ @@ -1771,9 +1776,10 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); /* compressor.c */ int __init ubifs_compressors_init(void); void ubifs_compressors_exit(void); +int ubifs_aes_crypt(void *str, int len, u8 *crypto_key, u8 *iv); void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, int *compr_type, u8 *crypto_key); -int ubifs_decompress(const void *buf, int len, void *out, int *out_len, +int ubifs_decompress(void *buf, int len, void *out, int *out_len, int compr_type, u8 *crypto_key); #include "debug.h" -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html