summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-07-07 08:00:00 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-07-07 08:00:00 -0600
commit54ad2ccf1760e9ffa49e563259e110ed464b3c94 (patch)
tree0cbfd5bc12ec46a00afbde11bce96fbb1d57ac49
parentda5378a9e4f4bebdff091f2a277827c9556d271a (diff)
downloadnuttx-54ad2ccf1760e9ffa49e563259e110ed464b3c94.tar.gz
nuttx-54ad2ccf1760e9ffa49e563259e110ed464b3c94.tar.bz2
nuttx-54ad2ccf1760e9ffa49e563259e110ed464b3c94.zip
BCH: Add configurable AES encryption support to block-to-character (BCH) driver. This allows any block device to be accessed as an encrypted character device. From Max Nekludov
-rw-r--r--nuttx/drivers/bch/Kconfig10
-rw-r--r--nuttx/drivers/bch/bch_internal.h6
-rw-r--r--nuttx/drivers/bch/bchdev_driver.c10
-rw-r--r--nuttx/drivers/bch/bchlib_cache.c79
-rw-r--r--nuttx/include/nuttx/fs/ioctl.h4
5 files changed, 106 insertions, 3 deletions
diff --git a/nuttx/drivers/bch/Kconfig b/nuttx/drivers/bch/Kconfig
index ae2bf3130..514683a09 100644
--- a/nuttx/drivers/bch/Kconfig
+++ b/nuttx/drivers/bch/Kconfig
@@ -2,3 +2,13 @@
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
+
+config BCH_ENCRYPTION
+ bool "Enable encryption feature"
+ default n
+ depends on CRYPTO_AES
+
+config BCH_ENCRYPTION_KEY_SIZE
+ int "AES key size"
+ default 16
+ depends on BCH_ENCRYPTION \ No newline at end of file
diff --git a/nuttx/drivers/bch/bch_internal.h b/nuttx/drivers/bch/bch_internal.h
index fb1c64236..dabd2f5c5 100644
--- a/nuttx/drivers/bch/bch_internal.h
+++ b/nuttx/drivers/bch/bch_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/bch/bch_internal.h
*
- * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2008-2009, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,10 @@ struct bchlib_s
bool dirty; /* Data has been written to the buffer */
bool readonly; /* true: Only read operations are supported */
FAR uint8_t *buffer; /* One sector buffer */
+
+#if defined(CONFIG_BCH_ENCRYPTION)
+ uint8_t key[CONFIG_BCH_ENCRYPTION_KEY_SIZE]; /* Encryption key */
+#endif
};
/****************************************************************************
diff --git a/nuttx/drivers/bch/bchdev_driver.c b/nuttx/drivers/bch/bchdev_driver.c
index 597710d99..6db09674d 100644
--- a/nuttx/drivers/bch/bchdev_driver.c
+++ b/nuttx/drivers/bch/bchdev_driver.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/bch/bchdev_driver.c
*
- * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2008-2009, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -186,6 +186,7 @@ static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
filep->f_pos += len;
}
+
bchlib_semgive(bch);
return ret;
}
@@ -249,6 +250,13 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
bchlib_semgive(bch);
}
+#if defined(CONFIG_BCH_ENCRYPTION)
+ else if (cmd == DIOC_SETKEY)
+ {
+ memcpy(bch->key, (void*)arg, CONFIG_BCH_ENCRYPTION_KEY_SIZE);
+ ret = OK;
+ }
+#endif
return ret;
}
diff --git a/nuttx/drivers/bch/bchlib_cache.c b/nuttx/drivers/bch/bchlib_cache.c
index 3b8212a13..3e46c2405 100644
--- a/nuttx/drivers/bch/bchlib_cache.c
+++ b/nuttx/drivers/bch/bchlib_cache.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/bch/bchlib_cache.c
*
- * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2008-2009, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -49,6 +49,10 @@
#include "bch_internal.h"
+#if defined(CONFIG_BCH_ENCRYPTION)
+# include <crypto/crypto.h>
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -66,6 +70,51 @@
****************************************************************************/
/****************************************************************************
+ * Name: bch_xor
+ ****************************************************************************/
+
+#if defined(CONFIG_BCH_ENCRYPTION)
+static void bch_xor(uint32_t *R, uint32_t *A, uint32_t *B)
+{
+ R[0] = A[0] ^ B[0];
+ R[1] = A[1] ^ B[1];
+ R[2] = A[2] ^ B[2];
+ R[3] = A[3] ^ B[3];
+}
+#endif
+
+/****************************************************************************
+ * Name: bch_cypher
+ ****************************************************************************/
+
+#if defined(CONFIG_BCH_ENCRYPTION)
+static int bch_cypher(FAR struct bchlib_s *bch, int encrypt)
+{
+ int blocks = bch->sectsize / 16;
+ uint32_t *buffer = (uint32_t*)bch->buffer;
+ int i;
+
+ for (i = 0; i < blocks; i++, buffer += 16 / sizeof(uint32_t) )
+ {
+ uint32_t T[4];
+ uint32_t X[4] = {bch->sector, 0, 0, i};
+
+ aes_cypher(X, X, 16, NULL, bch->key, CONFIG_BCH_ENCRYPTION_KEY_SIZE,
+ AES_MODE_ECB, CYPHER_ENCRYPT);
+
+ /* Xor-Encrypt-Xor */
+
+ bch_xor(T, X, buffer);
+ aes_cypher(T, T, 16, NULL, bch->key, CONFIG_BCH_ENCRYPTION_KEY_SIZE,
+ AES_MODE_ECB, encrypt);
+ bch_xor(buffer, X, T);
+ }
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -85,16 +134,41 @@ int bchlib_flushsector(FAR struct bchlib_s *bch)
FAR struct inode *inode;
ssize_t ret = OK;
+ /* Check if the sector has been modified and is out of synch with the
+ * media.
+ */
+
if (bch->dirty)
{
inode = bch->inode;
+
+#if defined(CONFIG_BCH_ENCRYPTION)
+ /* Encrypt data as necessary */
+
+ bch_cypher(bch, CYPHER_ENCRYPT);
+#endif
+
+ /* Write the sector to the media */
+
ret = inode->u.i_bops->write(inode, bch->buffer, bch->sector, 1);
if (ret < 0)
{
fdbg("Write failed: %d\n");
}
+
+#if defined(CONFIG_BCH_ENCRYPTION)
+ /* Computation overhead to save memory for extra sector buffer
+ * TODO: Add configuration switch for extra sector buffer
+ */
+
+ bch_cypher(bch, CYPHER_DECRYPT);
+#endif
+
+ /* The sector is now in sync with the media */
+
bch->dirty = false;
}
+
return (int)ret;
}
@@ -127,6 +201,9 @@ int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector)
fdbg("Read failed: %d\n");
}
bch->sector = sector;
+#if defined(CONFIG_BCH_ENCRYPTION)
+ bch_cypher(bch, CYPHER_DECRYPT);
+#endif
}
return (int)ret;
}
diff --git a/nuttx/include/nuttx/fs/ioctl.h b/nuttx/include/nuttx/fs/ioctl.h
index 25c3c6d95..1d8e32920 100644
--- a/nuttx/include/nuttx/fs/ioctl.h
+++ b/nuttx/include/nuttx/fs/ioctl.h
@@ -143,6 +143,10 @@
* FIOC_GETPRIV released.
*/
+#define DIOC_SETKEY _DIOC(0X0004) /* IN: Encryption key
+ * OUT: None
+ */
+
/* NuttX block driver ioctl definitions *************************************/
#define _BIOCVALID(c) (_IOC_TYPE(c)==_BIOCBASE)