From patchwork Sun Mar 25 21:38:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Reardon X-Patchwork-Id: 148587 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:4978:20e::2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B1A01B6EE7 for ; Mon, 26 Mar 2012 08:39:34 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SBv8e-0004Ys-Qs; Sun, 25 Mar 2012 21:38:12 +0000 Received: from [78.46.68.141] (helo=eristoteles.iwoars.net) by merlin.infradead.org with smtp (Exim 4.76 #1 (Red Hat Linux)) id 1SBv8b-0004Ye-L0 for linux-mtd@lists.infradead.org; Sun, 25 Mar 2012 21:38:10 +0000 Received: (qmail 8369 invoked by uid 5144); 25 Mar 2012 23:38:08 +0200 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 25 Mar 2012 23:38:08 +0200 Date: Sun, 25 Mar 2012 23:38:08 +0200 (CEST) From: Joel Reardon X-X-Sender: joel@eristoteles.iwoars.net To: Artem Bityutskiy Subject: [patch] Add cryptographic functionality when a key is passed to the compress / decompress functions In-Reply-To: Message-ID: References: <1330531826.3545.128.camel@sauron.fi.intel.com> <1332511796.18717.72.camel@sauron.fi.intel.com> <1332521515.22278.2.camel@sauron.fi.intel.com> User-Agent: Alpine 2.00 (DEB 1167 2008-08-23) MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -0.8 (/) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-0.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.8 RDNS_NONE Delivered to internal network by a host with no rDNS 0.3 FROM_12LTRDOM From a 12-letter domain Cc: linux-fsdevel@vger.kernel.org, linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This patch adds a function to perform AES encryption. The compress and decompress routines use this function if they are called with a non-NULL key parameter. It uses AES counter mode (where encryption and decryption are the same function) and performs the operation in place on the data. It uses a default IV of 0, since each key is only evey used to encrypt one data item the IV does not matter. The const qualifier was removed from the decompress routine for the following reason. Encrypted data is not compressable, so compression is first applied then the result is encrypted. In the reverse, decryption is first applied and the result decompressed. This means that either the input buffer for decompression is used to perform an in-place decryption before decompression, or a third buffer is added and data is copied around. Signed-off-by: Joel Reardon diff --git a/fs/ubifs/compress.c b/fs/ubifs/compress.c index d1812fa..b738ab0 100644 --- a/fs/ubifs/compress.c +++ b/fs/ubifs/compress.c @@ -27,9 +27,12 @@ * decompression. */ -#include #include "ubifs.h" +#include +#include + + /* 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 + * @key: the key to use to crypt the data + * @key_len: the length of the key + * @iv: the initialization vector to use + * @ivlen: the length of the initialization vector + * + * 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. + */ +int ubifs_aes_crypt(void *str, int len, u8 *key, int keylen, u8 *iv, int ivlen) +{ + 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, key, keylen); + desc.tfm = tfm; + desc.flags = 0; + if (err) { + ubifs_err("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 @@ -127,12 +177,21 @@ 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; + goto encrypt; + +encrypt: + if (key) { + u8 iv[UBIFS_CRYPTO_KEYSIZE]; + memset(iv, 0, UBIFS_CRYPTO_KEYSIZE); + ubifs_aes_crypt(out_buf, *out_len, key, UBIFS_CRYPTO_KEYSIZE, + iv, UBIFS_CRYPTO_KEYSIZE); + } } /** @@ -149,7 +208,7 @@ no_compr: * The length of the uncompressed data is returned in @out_len. This functions * returns %0 on success or a negative error code on failure. */ -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 *key) { int err; @@ -167,6 +226,13 @@ int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, return -EINVAL; } + if (key) { + u8 iv[UBIFS_CRYPTO_KEYSIZE]; + memset(iv, 0, UBIFS_CRYPTO_KEYSIZE); + ubifs_aes_crypt(in_buf, in_len, key, UBIFS_CRYPTO_KEYSIZE, + iv, UBIFS_CRYPTO_KEYSIZE); + } + 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 0cc1180..923babe 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -160,6 +160,14 @@ /* Maximum number of data nodes to bulk-read */ #define UBIFS_MAX_BULK_READ 32 +/* Size of 128 bits in bytes */ +#define AES_KEYSIZE_128 16 + +/* Key size in bytes for UBIFS */ +#define UBIFS_CRYPTO_KEYSIZE AES_KEYSIZE_128 +/* AES in counter mode is the encryption algorithm. */ +#define UBIFS_CRYPTO_ALGORITHM "ctr(aes)" + /* * Lockdep classes for UBIFS inode @ui_mutex. */ @@ -1771,9 +1779,11 @@ 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 *key, int keylen, + u8 *iv, int ivlen); void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, int *compr_type, u8 *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 *key); #include "debug.h"