From dc7bcb0c1d7332f234c1a04cb525a511b6ea4849 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 7 Jul 2014 08:00:00 -0600 Subject: [PATCH] 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 --- drivers/bch/Kconfig | 10 +++++ drivers/bch/bch_internal.h | 6 ++- drivers/bch/bchdev_driver.c | 10 ++++- drivers/bch/bchlib_cache.c | 79 ++++++++++++++++++++++++++++++++++++- include/nuttx/fs/ioctl.h | 4 ++ 5 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/bch/Kconfig b/drivers/bch/Kconfig index ae2bf31307..514683a09a 100644 --- a/drivers/bch/Kconfig +++ b/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/drivers/bch/bch_internal.h b/drivers/bch/bch_internal.h index fb1c642367..dabd2f5c50 100644 --- a/drivers/bch/bch_internal.h +++ b/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 * * 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/drivers/bch/bchdev_driver.c b/drivers/bch/bchdev_driver.c index 597710d99d..6db09674d4 100644 --- a/drivers/bch/bchdev_driver.c +++ b/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 * * 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/drivers/bch/bchlib_cache.c b/drivers/bch/bchlib_cache.c index 3b8212a13f..3e46c24057 100644 --- a/drivers/bch/bchlib_cache.c +++ b/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 * * 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 +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -65,6 +69,51 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * 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/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index 25c3c6d956..1d8e32920c 100644 --- a/include/nuttx/fs/ioctl.h +++ b/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)